mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-26 00:12:31 +01:00
Merge branch 'wmdrawer' into next
This commit is contained in:
@@ -419,6 +419,12 @@ typedef struct WPreferences {
|
||||
char cycle_active_head_only; /* Cycle only windows on the active head */
|
||||
char cycle_ignore_minimized; /* Ignore minimized windows when cycling */
|
||||
|
||||
/* All delays here are in ms. 0 means instant auto-action. */
|
||||
int clip_auto_raise_delay; /* Delay after which the clip will be raised when entered */
|
||||
int clip_auto_lower_delay; /* Delay after which the clip will be lowered when leaved */
|
||||
int clip_auto_expand_delay; /* Delay after which the clip will expand when entered */
|
||||
int clip_auto_collapse_delay; /* Delay after which the clip will collapse when leaved */
|
||||
|
||||
RImage *swtileImage;
|
||||
RImage *swbackImage[9];
|
||||
|
||||
@@ -427,6 +433,9 @@ typedef struct WPreferences {
|
||||
struct {
|
||||
unsigned int nodock:1; /* don't display the dock */
|
||||
unsigned int noclip:1; /* don't display the clip */
|
||||
unsigned int clip_merged_in_dock:1; /* disable clip, dock gets its workspace switching functionality */
|
||||
unsigned int nodrawer:1; /* don't use drawers */
|
||||
unsigned int wrap_appicons_in_dock:1; /* Whether to wrap appicons when Dock is moved up and down */
|
||||
unsigned int noupdates:1; /* don't require ~/GNUstep (-static) */
|
||||
unsigned int noautolaunch:1; /* don't autolaunch apps */
|
||||
unsigned int norestore:1; /* don't restore session */
|
||||
|
||||
453
src/appicon.c
453
src/appicon.c
@@ -64,6 +64,7 @@ extern WDDomain *WDWindowAttributes;
|
||||
extern XContext wWinContext;
|
||||
|
||||
#define MOD_MASK wPreferences.modifier_mask
|
||||
#define ICON_SIZE wPreferences.icon_size
|
||||
|
||||
void appIconMouseDown(WObjDescriptor * desc, XEvent * event);
|
||||
static void iconDblClick(WObjDescriptor * desc, XEvent * event);
|
||||
@@ -129,6 +130,8 @@ WAppIcon *wAppIconCreateForDock(WScreen *scr, char *command, char *wm_instance,
|
||||
if (wm_instance)
|
||||
aicon->wm_instance = wstrdup(wm_instance);
|
||||
|
||||
if (strcmp(wm_class, "WMDock") == 0 && wPreferences.flags.clip_merged_in_dock)
|
||||
tile = TILE_CLIP;
|
||||
aicon->icon = icon_create_for_dock(scr, command, wm_instance, wm_class, tile);
|
||||
|
||||
#ifdef XDND
|
||||
@@ -199,7 +202,7 @@ void paint_app_icon(WApplication *wapp)
|
||||
{
|
||||
WIcon *icon;
|
||||
WScreen *scr = wapp->main_window_desc->screen_ptr;
|
||||
WDock *clip = scr->workspaces[scr->current_workspace]->clip;
|
||||
WDock *attracting_dock;
|
||||
int x = 0, y = 0;
|
||||
Bool update_icon = False;
|
||||
|
||||
@@ -213,13 +216,17 @@ void paint_app_icon(WApplication *wapp)
|
||||
if (wapp->app_icon->docked)
|
||||
return;
|
||||
|
||||
if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
|
||||
attracting_dock = scr->attracting_drawer != NULL ?
|
||||
scr->attracting_drawer :
|
||||
scr->workspaces[scr->current_workspace]->clip;
|
||||
if (attracting_dock && attracting_dock->attract_icons &&
|
||||
wDockFindFreeSlot(attracting_dock, &x, &y)) {
|
||||
wapp->app_icon->attracted = 1;
|
||||
if (!icon->shadowed) {
|
||||
icon->shadowed = 1;
|
||||
update_icon = True;
|
||||
}
|
||||
wDockAttachIcon(clip, wapp->app_icon, x, y, update_icon);
|
||||
wDockAttachIcon(attracting_dock, wapp->app_icon, x, y, update_icon);
|
||||
} else {
|
||||
/* We must know if the icon is painted in the screen,
|
||||
* because if painted, then PlaceIcon will return the next
|
||||
@@ -238,7 +245,7 @@ void paint_app_icon(WApplication *wapp)
|
||||
wapp->app_icon->next == NULL && wapp->app_icon->prev == NULL)
|
||||
add_to_appicon_list(scr, wapp->app_icon);
|
||||
|
||||
if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
|
||||
if (!attracting_dock || !wapp->app_icon->attracted || !attracting_dock->collapsed)
|
||||
XMapWindow(dpy, icon->core->window);
|
||||
|
||||
if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
|
||||
@@ -273,6 +280,9 @@ void removeAppIconFor(WApplication *wapp)
|
||||
wAppIconPaint(wapp->app_icon);
|
||||
} else if (wapp->app_icon->docked) {
|
||||
wapp->app_icon->running = 0;
|
||||
if (wapp->app_icon->dock->type == WM_DRAWER) {
|
||||
wDrawerFillTheGap(wapp->app_icon->dock, wapp->app_icon, True);
|
||||
}
|
||||
wDockDetach(wapp->app_icon->dock, wapp->app_icon);
|
||||
} else {
|
||||
wAppIconDestroy(wapp->app_icon);
|
||||
@@ -671,24 +681,8 @@ static void iconDblClick(WObjDescriptor *desc, XEvent *event)
|
||||
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;
|
||||
WScreen *scr = aicon->icon->core->screen_ptr;
|
||||
Bool hasMoved;
|
||||
|
||||
if (aicon->editing || WCHECK_STATE(WSTATE_MODAL))
|
||||
return;
|
||||
@@ -733,24 +727,98 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->xbutton.state & MOD_MASK)
|
||||
wLowerFrame(icon->core);
|
||||
else
|
||||
hasMoved = wHandleAppIconMove(aicon, event);
|
||||
if (wPreferences.single_click && !hasMoved && aicon->dock != NULL)
|
||||
{
|
||||
iconDblClick(desc, event);
|
||||
}
|
||||
}
|
||||
|
||||
Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event)
|
||||
{
|
||||
WIcon *icon = aicon->icon;
|
||||
WScreen *scr = icon->core->screen_ptr;
|
||||
WDock *originalDock = aicon->dock; /* can be NULL */
|
||||
WDock *lastDock = originalDock;
|
||||
WDock *allDocks[scr->drawer_count + 2]; /* clip, dock and drawers (order determined at runtime) */
|
||||
WDrawerChain *dc;
|
||||
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;
|
||||
|
||||
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);
|
||||
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
|
||||
| ButtonReleaseMask | ButtonPressMask, GrabModeAsync,
|
||||
GrabModeAsync, None, None, CurrentTime) != GrabSuccess)
|
||||
wwarning("pointer grab failed for appicon move");
|
||||
GrabModeAsync, None, None, CurrentTime) != GrabSuccess) {
|
||||
wwarning("Pointer grab failed in wHandleAppIconMove");
|
||||
}
|
||||
|
||||
if (wPreferences.flags.nodock && wPreferences.flags.noclip)
|
||||
dockable = 0;
|
||||
else
|
||||
dockable = canBeDocked(icon->owner);
|
||||
if (originalDock != NULL) {
|
||||
dockable = True;
|
||||
ondock = True;
|
||||
}
|
||||
else {
|
||||
ondock = False;
|
||||
if (wPreferences.flags.nodock && wPreferences.flags.noclip && wPreferences.flags.nodrawer)
|
||||
dockable = 0;
|
||||
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 scr->drawers is enough, no need to test wPreferences.flags.nodrawer */
|
||||
for (dc = scr->drawers; dc != NULL; dc = dc->next) {
|
||||
if (dc->adrawer != originalDock)
|
||||
allDocks[ i++ ] = dc->adrawer;
|
||||
}
|
||||
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 < scr->drawer_count + 2; i++) /* In case the clip, the dock, or both, are disabled */
|
||||
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(scr, icon->pixmap);
|
||||
@@ -759,6 +827,8 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost);
|
||||
XClearWindow(dpy, scr->dock_shadow);
|
||||
}
|
||||
if (ondock)
|
||||
XMapWindow(dpy, scr->dock_shadow);
|
||||
|
||||
while (!done) {
|
||||
WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask
|
||||
@@ -768,18 +838,18 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
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 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;
|
||||
if (!grabbed) {
|
||||
if (abs(dx - ev.xmotion.x) >= MOVE_THRESHOLD
|
||||
|| abs(dy - ev.xmotion.y) >= MOVE_THRESHOLD) {
|
||||
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);
|
||||
@@ -788,68 +858,92 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
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;
|
||||
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;
|
||||
wAppIconMove(aicon, x, y);
|
||||
|
||||
WDock *theNewDock = NULL;
|
||||
if (!(ev.xmotion.state & MOD_MASK) || aicon->launching || aicon->lock) {
|
||||
for (i = 0; dockable && i < scr->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;
|
||||
}
|
||||
}
|
||||
if (originalDock != NULL && theNewDock == NULL &&
|
||||
(aicon->launching || aicon->lock || aicon->running)) {
|
||||
/* In those cases, stay in lastDock if no dock really wants us */
|
||||
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->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 = theNewDock; // i.e., NULL
|
||||
if (ondock) {
|
||||
XUnmapWindow(dpy, scr->dock_shadow);
|
||||
/*
|
||||
* Leaving that weird comment for now.
|
||||
* But if we see no gap, there is no need to fill one!
|
||||
* We could test ondock first and the lastDock to NULL afterwards
|
||||
if (lastDock_before_it_was_null->type == WM_DRAWER) {
|
||||
wDrawerFillTheGap(lastDock, aicon, (lastDock == originalDock));
|
||||
} */
|
||||
|
||||
}
|
||||
ondock = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -861,59 +955,130 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
break;
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
|
||||
if (docking) {
|
||||
Bool docked;
|
||||
|
||||
/* icon is trying to be docked */
|
||||
Bool docked = False;
|
||||
if (ondock) {
|
||||
SlideWindow(icon->core->window, x, y, shad_x, shad_y);
|
||||
XUnmapWindow(dpy, scr->dock_shadow);
|
||||
docked = wDockAttachIcon(scr->last_dock, aicon, ix, iy, False);
|
||||
if (scr->last_dock->auto_collapse)
|
||||
if (originalDock == NULL) { // docking an undocked appicon
|
||||
docked = wDockAttachIcon(lastDock, aicon, ix, iy, False);
|
||||
if (!docked) {
|
||||
/* AppIcon got rejected (happens only when we can't get the
|
||||
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 */
|
||||
if (lastDock->type == WM_DRAWER) {
|
||||
// Also fill the gap left in the drawer
|
||||
wDrawerFillTheGap(lastDock, aicon, False);
|
||||
}
|
||||
SlideWindow(icon->core->window, x, y, oldX, oldY);
|
||||
}
|
||||
}
|
||||
else { // moving a docked appicon to a dock
|
||||
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 */
|
||||
if (lastDock->type == WM_DRAWER) {
|
||||
wDrawerFillTheGap(lastDock, aicon, False);
|
||||
}
|
||||
/* If aicon comes from a drawer, make some room to reattach it */
|
||||
if (originalDock->type == WM_DRAWER) {
|
||||
WAppIcon *aiconsToShift[ originalDock->icon_count ];
|
||||
int j = 0;
|
||||
|
||||
for (i = 0; i < originalDock->max_icons; i++) {
|
||||
WAppIcon *ai = originalDock->icon_array[ i ];
|
||||
if (ai && ai != aicon &&
|
||||
abs(ai->xindex) >= abs(aicon->xindex))
|
||||
aiconsToShift[j++] = ai;
|
||||
}
|
||||
if (j != originalDock->icon_count - abs(aicon->xindex) - 1)
|
||||
// Trust this never happens?
|
||||
wwarning("Shifting j=%d appicons (instead of %d!) to reinsert aicon at index %d.",
|
||||
j, originalDock->icon_count - abs(aicon->xindex) - 1, aicon->xindex);
|
||||
wSlideAppicons(aiconsToShift, j, originalDock->on_right_side);
|
||||
// Trust the appicon is inserted at exactly the same place, so its oldX/oldY are consistent with its "new" location?
|
||||
}
|
||||
|
||||
SlideWindow(icon->core->window, x, y, oldX, oldY);
|
||||
wDockReattachIcon(originalDock, aicon, aicon->xindex, aicon->yindex);
|
||||
}
|
||||
else {
|
||||
if (originalDock->auto_collapse && !originalDock->collapsed) {
|
||||
originalDock->collapsed = 1;
|
||||
wDockHideIcons(originalDock);
|
||||
}
|
||||
if (originalDock->auto_raise_lower)
|
||||
wDockLower(originalDock);
|
||||
}
|
||||
}
|
||||
}
|
||||
// No matter what happened above, check to lower lastDock
|
||||
// Don't see why I commented out the following 2 lines
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
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 (originalDock->auto_collapse && !originalDock->collapsed) {
|
||||
originalDock->collapsed = 1;
|
||||
wDockHideIcons(originalDock);
|
||||
}
|
||||
if (originalDock->auto_raise_lower)
|
||||
wDockLower(originalDock);
|
||||
}
|
||||
}
|
||||
// Can't remember why the icon hiding is better done above than below (commented out)
|
||||
// Also, lastDock is quite different from originalDock
|
||||
/*
|
||||
if (collapsed) {
|
||||
lastDock->collapsed = 1;
|
||||
wDockHideIcons(lastDock);
|
||||
collapsed = 0;
|
||||
}
|
||||
*/
|
||||
if (superfluous) {
|
||||
if (ghost != None)
|
||||
XFreePixmap(dpy, ghost);
|
||||
XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel);
|
||||
}
|
||||
|
||||
if (wPreferences.auto_arrange_icons)
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (wPreferences.auto_arrange_icons && !(originalDock != NULL && docked))
|
||||
/* Need to rearrange unless moving from dock to dock */
|
||||
wArrangeIcons(scr, True);
|
||||
|
||||
if (wPreferences.single_click && !hasMoved)
|
||||
iconDblClick(desc, event);
|
||||
|
||||
done = 1;
|
||||
break;
|
||||
return hasMoved;
|
||||
}
|
||||
}
|
||||
return False; /* Never reached */
|
||||
}
|
||||
|
||||
/* This function save the application icon and store the path in the Dictionary */
|
||||
@@ -980,7 +1145,7 @@ static void create_appicon_from_dock(WWindow *wwin, WApplication *wapp, Window m
|
||||
if (!wapp->app_icon && scr->dock)
|
||||
wapp->app_icon = findDockIconFor(scr->dock, main_window);
|
||||
|
||||
/* finally check clips */
|
||||
/* check clips */
|
||||
if (!wapp->app_icon) {
|
||||
int i;
|
||||
for (i = 0; i < scr->workspace_count; i++) {
|
||||
@@ -992,6 +1157,16 @@ static void create_appicon_from_dock(WWindow *wwin, WApplication *wapp, Window m
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally check drawers */
|
||||
if (!wapp->app_icon) {
|
||||
WDrawerChain *dc;
|
||||
for (dc = scr->drawers; dc != NULL; dc = dc->next) {
|
||||
wapp->app_icon = findDockIconFor(dc->adrawer, main_window);
|
||||
if (wapp->app_icon)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If created, then set some flags */
|
||||
if (wapp->app_icon) {
|
||||
WWindow *mainw = wapp->main_window_desc;
|
||||
|
||||
@@ -71,6 +71,7 @@ typedef struct WAppIcon {
|
||||
|
||||
WAppIcon *wAppIconCreateForDock(WScreen *scr, char *command, char *wm_instance,
|
||||
char *wm_class, int tile);
|
||||
Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event);
|
||||
|
||||
void wAppIconDestroy(WAppIcon *aicon);
|
||||
void wAppIconPaint(WAppIcon *aicon);
|
||||
|
||||
@@ -113,6 +113,8 @@ static int getPropList();
|
||||
static int setJustify();
|
||||
static int setClearance();
|
||||
static int setIfDockPresent();
|
||||
static int setClipMergedInDock();
|
||||
static int setWrapAppiconsInDock();
|
||||
static int setStickyIcons();
|
||||
static int setWidgetColor();
|
||||
static int setIconTile();
|
||||
@@ -332,6 +334,10 @@ WDefaultEntry staticOptionList[] = {
|
||||
NULL, getBool, setIfDockPresent, NULL, NULL},
|
||||
{"DisableClip", "NO", (void *)WM_CLIP,
|
||||
NULL, getBool, setIfDockPresent, NULL, NULL},
|
||||
{"DisableDrawers", "NO", (void *)WM_DRAWER,
|
||||
NULL, getBool, setIfDockPresent, NULL, NULL},
|
||||
{"ClipMergedInDock", "NO", NULL,
|
||||
NULL, getBool, setClipMergedInDock, NULL, NULL},
|
||||
{"DisableMiniwindows", "NO", NULL,
|
||||
&wPreferences.disable_miniwindows, getBool, NULL, NULL, NULL}
|
||||
};
|
||||
@@ -401,6 +407,16 @@ WDefaultEntry optionList[] = {
|
||||
&wPreferences.do_not_make_appicons_bounce, getBool, NULL, NULL, NULL},
|
||||
{"DoubleClickTime", "250", (void *)&wPreferences.dblclick_time,
|
||||
&wPreferences.dblclick_time, getInt, setDoubleClick, NULL, NULL},
|
||||
{"ClipAutoraiseDelay", "600", NULL,
|
||||
&wPreferences.clip_auto_raise_delay, getInt, NULL, NULL, NULL},
|
||||
{"ClipAutolowerDelay", "1000", NULL,
|
||||
&wPreferences.clip_auto_lower_delay, getInt, NULL, NULL, NULL},
|
||||
{"ClipAutoexpandDelay", "600", NULL,
|
||||
&wPreferences.clip_auto_expand_delay, getInt, NULL, NULL, NULL},
|
||||
{"ClipAutocollapseDelay", "1000", NULL,
|
||||
&wPreferences.clip_auto_collapse_delay, getInt, NULL, NULL, NULL},
|
||||
{"WrapAppiconsInDock", "YES", NULL,
|
||||
NULL, getBool, setWrapAppiconsInDock, NULL, NULL},
|
||||
{"AlignSubmenus", "NO", NULL,
|
||||
&wPreferences.align_menus, getBool, NULL, NULL, NULL},
|
||||
{"ViKeyMenus", "NO", NULL,
|
||||
@@ -1180,6 +1196,7 @@ void wReadDefaults(WScreen * scr, WMPropList * new_dict)
|
||||
void wDefaultUpdateIcons(WScreen *scr)
|
||||
{
|
||||
WAppIcon *aicon = scr->app_icon_list;
|
||||
WDrawerChain *dc;
|
||||
WWindow *wwin = scr->focused_window;
|
||||
|
||||
while (aicon) {
|
||||
@@ -1189,9 +1206,12 @@ void wDefaultUpdateIcons(WScreen *scr)
|
||||
aicon = aicon->next;
|
||||
}
|
||||
|
||||
if (!wPreferences.flags.noclip)
|
||||
if (!wPreferences.flags.noclip || wPreferences.flags.clip_merged_in_dock)
|
||||
wClipIconPaint(scr->clip_icon);
|
||||
|
||||
for (dc = scr->drawers; dc != NULL; dc = dc->next)
|
||||
wDrawerIconPaint(dc->adrawer->icon_array[0]);
|
||||
|
||||
while (wwin) {
|
||||
if (wwin->icon && wwin->flags.miniaturized)
|
||||
wIconChangeImageFile(wwin->icon, NULL);
|
||||
@@ -2373,16 +2393,34 @@ static int setIfDockPresent(WScreen * scr, WDefaultEntry * entry, char *flag, lo
|
||||
switch (which) {
|
||||
case WM_DOCK:
|
||||
wPreferences.flags.nodock = wPreferences.flags.nodock || *flag;
|
||||
// Drawers require the dock
|
||||
wPreferences.flags.nodrawer = wPreferences.flags.nodrawer || wPreferences.flags.nodock;
|
||||
break;
|
||||
case WM_CLIP:
|
||||
wPreferences.flags.noclip = wPreferences.flags.noclip || *flag;
|
||||
break;
|
||||
case WM_DRAWER:
|
||||
wPreferences.flags.nodrawer = wPreferences.flags.nodrawer || *flag;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setClipMergedInDock(WScreen *scr, WDefaultEntry *entry, char *flag, void *foo)
|
||||
{
|
||||
wPreferences.flags.clip_merged_in_dock = *flag;
|
||||
wPreferences.flags.noclip = wPreferences.flags.noclip || *flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setWrapAppiconsInDock(WScreen *scr, WDefaultEntry *entry, char *flag, void *foo)
|
||||
{
|
||||
wPreferences.flags.wrap_appicons_in_dock = *flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setStickyIcons(WScreen * scr, WDefaultEntry * entry, void *bar, void *foo)
|
||||
{
|
||||
if (scr->workspaces) {
|
||||
@@ -2420,13 +2458,20 @@ static int setIconTile(WScreen * scr, WDefaultEntry * entry, WTexture ** texture
|
||||
/* put the icon in the noticeboard hint */
|
||||
PropSetIconTileHint(scr, img);
|
||||
|
||||
if (!wPreferences.flags.noclip) {
|
||||
if (!wPreferences.flags.noclip || wPreferences.flags.clip_merged_in_dock) {
|
||||
if (scr->clip_tile) {
|
||||
RReleaseImage(scr->clip_tile);
|
||||
}
|
||||
scr->clip_tile = wClipMakeTile(scr, img);
|
||||
}
|
||||
|
||||
if (!wPreferences.flags.nodrawer) {
|
||||
if (scr->drawer_tile) {
|
||||
RReleaseImage(scr->drawer_tile);
|
||||
}
|
||||
scr->drawer_tile = wDrawerMakeTile(scr, img);
|
||||
}
|
||||
|
||||
scr->icon_tile_pixmap = pixmap;
|
||||
|
||||
if (scr->def_icon_rimage) {
|
||||
|
||||
@@ -54,4 +54,7 @@ char *get_icon_filename(WScreen *scr, char *winstance, char *wclass, char *comma
|
||||
int wDefaultGetStartWorkspace(WScreen *scr, char *instance, char *class);
|
||||
void wDefaultChangeIcon(WScreen *scr, char *instance, char* class, char *file);
|
||||
RImage *get_rimage_from_file(WScreen *scr, char *file_name, int max_size);
|
||||
|
||||
void wDefaultPurgeInfo(WScreen *scr, char *instance, char *class);
|
||||
|
||||
#endif /* WMDEFAULTS_H_ */
|
||||
|
||||
1932
src/dock.c
1932
src/dock.c
File diff suppressed because it is too large
Load Diff
21
src/dock.h
21
src/dock.h
@@ -39,6 +39,7 @@ typedef struct WDock {
|
||||
|
||||
#define WM_DOCK 0
|
||||
#define WM_CLIP 1
|
||||
#define WM_DRAWER 2
|
||||
int type;
|
||||
|
||||
WMagicNumber auto_expand_magic;
|
||||
@@ -66,7 +67,7 @@ typedef struct WDock {
|
||||
|
||||
|
||||
|
||||
WDock *wDockCreate(WScreen *scr, int type);
|
||||
WDock *wDockCreate(WScreen *scr, int type, char *name);
|
||||
WDock *wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type);
|
||||
|
||||
void wDockDestroy(WDock *dock);
|
||||
@@ -82,6 +83,11 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y,
|
||||
int *ret_x, int *ret_y, int redocking);
|
||||
Bool wDockFindFreeSlot(WDock *dock, int *req_x, int *req_y);
|
||||
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 wSlideAppicons(WAppIcon **appicons, int n, int to_the_left);
|
||||
void wDrawerFillTheGap(WDock *drawer, WAppIcon *aicon, Bool redocking);
|
||||
|
||||
void wDockFinishLaunch(WDock *dock, WAppIcon *icon);
|
||||
void wDockTrackWindowLaunch(WDock *dock, Window window);
|
||||
@@ -98,14 +104,27 @@ void wClipSaveState(WScreen *scr);
|
||||
WMPropList *wClipSaveWorkspaceState(WScreen *scr, int workspace);
|
||||
WAppIcon *wClipRestoreState(WScreen *scr, WMPropList *clip_state);
|
||||
|
||||
void wDrawerIconPaint(WAppIcon *dicon);
|
||||
void wDrawersSaveState(WScreen *scr);
|
||||
void wDrawersRestoreState(WScreen *scr);
|
||||
int wIsADrawer(WScreen *scr, WAppIcon *aicon);
|
||||
|
||||
void wClipUpdateForWorkspaceChange(WScreen *scr, int workspace);
|
||||
|
||||
RImage *wClipMakeTile(WScreen *scr, RImage *normalTile);
|
||||
RImage* wDrawerMakeTile(WScreen *scr, RImage *normalTile);
|
||||
|
||||
#define WO_FAILED 0
|
||||
#define WO_NOT_APPLICABLE 1
|
||||
#define WO_SUCCESS 2
|
||||
|
||||
typedef enum
|
||||
{
|
||||
P_NORMAL = 0,
|
||||
P_AUTO_RAISE_LOWER,
|
||||
P_KEEP_ON_TOP,
|
||||
} dockPosition;
|
||||
|
||||
int wClipMakeIconOmnipresent(WAppIcon *aicon, int omnipresent);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -177,8 +177,11 @@ static void panelBtnCallback(WMWidget * self, void *data)
|
||||
} else {
|
||||
WAppIcon *aicon = panel->editedIcon;
|
||||
|
||||
// Cf dock.c:dockIconPaint(WAppIcon *aicon)?
|
||||
if (aicon == aicon->icon->core->screen_ptr->clip_icon)
|
||||
wClipIconPaint(aicon);
|
||||
else if (wIsADrawer(aicon->icon->core->screen_ptr, aicon))
|
||||
wDrawerIconPaint(aicon);
|
||||
else
|
||||
wAppIconPaint(aicon);
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ WWindow * NextToFocusBefore(WWindow *wwin);
|
||||
|
||||
void move_window(Window win, int from_x, int from_y, int to_x, int to_y);
|
||||
void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y);
|
||||
void SlideWindows(Window *wins[], int n, int from_x, int from_y, int to_x, int to_y);
|
||||
|
||||
RImage * wGetImageForWindowName(WScreen *scr, char *winstance, char *wclass);
|
||||
|
||||
|
||||
14
src/icon.c
14
src/icon.c
@@ -246,11 +246,21 @@ static void icon_update_pixmap(WIcon *icon, RImage *image)
|
||||
int theight = 0;
|
||||
WScreen *scr = icon->core->screen_ptr;
|
||||
|
||||
if (icon->tile_type == TILE_NORMAL) {
|
||||
switch (icon->tile_type) {
|
||||
case TILE_NORMAL:
|
||||
tile = RCloneImage(scr->icon_tile);
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
wwarning("Unknown tileType: %d.\n", icon->tile_type);
|
||||
// fallthrough to TILE_CLIP (emulate previous behaviour)
|
||||
case TILE_CLIP:
|
||||
assert(scr->clip_tile);
|
||||
tile = RCloneImage(scr->clip_tile);
|
||||
break;
|
||||
case TILE_DRAWER:
|
||||
assert(scr->drawer_tile);
|
||||
tile = RCloneImage(scr->drawer_tile);
|
||||
break;
|
||||
}
|
||||
|
||||
if (image) {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#define TILE_NORMAL 0
|
||||
#define TILE_CLIP 1
|
||||
#define TILE_DRAWER 2
|
||||
|
||||
typedef struct WIcon {
|
||||
WCoreWindow *core;
|
||||
|
||||
@@ -686,8 +686,11 @@ static int real_main(int argc, char **argv)
|
||||
wPreferences.flags.norestore = 1;
|
||||
} else if (strcmp(argv[i], "-nodock") == 0 || strcmp(argv[i], "--no-dock") == 0) {
|
||||
wPreferences.flags.nodock = 1;
|
||||
wPreferences.flags.nodrawer = 1;
|
||||
} else if (strcmp(argv[i], "-noclip") == 0 || strcmp(argv[i], "--no-clip") == 0) {
|
||||
wPreferences.flags.noclip = 1;
|
||||
} else if (strcmp(argv[i], "-nodrawer") == 0 || strcmp(argv[i], "--no-drawer") == 0) {
|
||||
wPreferences.flags.nodrawer = 1;
|
||||
} else if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "--version") == 0) {
|
||||
printf("Window Maker %s\n", VERSION);
|
||||
exit(0);
|
||||
|
||||
19
src/misc.c
19
src/misc.c
@@ -51,6 +51,7 @@
|
||||
|
||||
/**** global variables *****/
|
||||
extern WPreferences wPreferences;
|
||||
#define ICON_SIZE wPreferences.icon_size
|
||||
|
||||
/* XFetchName Wrapper */
|
||||
Bool wFetchName(Display *dpy, Window win, char **winname)
|
||||
@@ -144,11 +145,21 @@ void move_window(Window win, int from_x, int from_y, int to_x, int to_y)
|
||||
}
|
||||
|
||||
void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
|
||||
{
|
||||
Window *wins[1] = { &win };
|
||||
SlideWindows(wins, 1, from_x, from_y, to_x, to_y);
|
||||
}
|
||||
|
||||
/* wins is an array of Window, sorted from left to right, the first is
|
||||
* going to be moved from (from_x,from_y) to (to_x,to_y) and the
|
||||
* following windows are going to be offset by (ICON_SIZE*i,0) */
|
||||
void SlideWindows(Window *wins[], int n, int from_x, int from_y, int to_x, int to_y)
|
||||
{
|
||||
time_t time0 = time(NULL);
|
||||
float dx, dy, x = from_x, y = from_y, sx, sy, px, py;
|
||||
int dx_is_bigger = 0;
|
||||
int slide_delay, slide_steps, slide_slowdown;
|
||||
int i;
|
||||
|
||||
/* animation parameters */
|
||||
static struct {
|
||||
@@ -216,7 +227,9 @@ void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
|
||||
px = (sy == 0 ? 0 : py * dx / dy);
|
||||
}
|
||||
|
||||
XMoveWindow(dpy, win, (int)x, (int)y);
|
||||
for (i = 0; i < n; i++) {
|
||||
XMoveWindow(dpy, *wins[i], (int)x + i * ICON_SIZE, (int)y);
|
||||
}
|
||||
XFlush(dpy);
|
||||
if (slide_delay > 0) {
|
||||
wusleep(slide_delay * 1000L);
|
||||
@@ -226,7 +239,9 @@ void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y)
|
||||
if (time(NULL) - time0 > MAX_ANIMATION_TIME)
|
||||
break;
|
||||
}
|
||||
XMoveWindow(dpy, win, to_x, to_y);
|
||||
for (i = 0; i < n; i++) {
|
||||
XMoveWindow(dpy, *wins[i], to_x + i * ICON_SIZE, to_y);
|
||||
}
|
||||
|
||||
XSync(dpy, 0);
|
||||
/* compress expose events */
|
||||
|
||||
17
src/screen.c
17
src/screen.c
@@ -94,6 +94,7 @@ static WMPropList *dApplications = NULL;
|
||||
static WMPropList *dWorkspace;
|
||||
static WMPropList *dDock;
|
||||
static WMPropList *dClip;
|
||||
static WMPropList *dDrawers = NULL;
|
||||
|
||||
static void make_keys(void)
|
||||
{
|
||||
@@ -104,6 +105,7 @@ static void make_keys(void)
|
||||
dWorkspace = WMCreatePLString("Workspace");
|
||||
dDock = WMCreatePLString("Dock");
|
||||
dClip = WMCreatePLString("Clip");
|
||||
dDrawers = WMCreatePLString("Drawers");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -842,12 +844,18 @@ void wScreenRestoreState(WScreen * scr)
|
||||
if (!wPreferences.flags.nodock) {
|
||||
state = WMGetFromPLDictionary(scr->session_state, dDock);
|
||||
scr->dock = wDockRestoreState(scr, state, WM_DOCK);
|
||||
/* If clip_merged_in_dock, setting scr->clip_icon is done by
|
||||
* wDockRestoreState()->wDockCreate()->mainIconCreate() */
|
||||
}
|
||||
|
||||
if (!wPreferences.flags.noclip) {
|
||||
state = WMGetFromPLDictionary(scr->session_state, dClip);
|
||||
scr->clip_icon = wClipRestoreState(scr, state);
|
||||
}
|
||||
|
||||
if (!wPreferences.flags.nodrawer) {
|
||||
wDrawersRestoreState(scr);
|
||||
}
|
||||
|
||||
wWorkspaceRestoreState(scr);
|
||||
|
||||
@@ -895,6 +903,15 @@ void wScreenSaveState(WScreen * scr)
|
||||
|
||||
wWorkspaceSaveState(scr, old_state);
|
||||
|
||||
if (!wPreferences.flags.nodrawer) {
|
||||
wDrawersSaveState(scr);
|
||||
} else {
|
||||
if ((foo = WMGetFromPLDictionary(old_state, dDrawers)) != NULL) {
|
||||
WMPutInPLDictionary(scr->session_state, dDrawers, foo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (wPreferences.save_session_on_exit) {
|
||||
wSessionSaveState(scr);
|
||||
} else {
|
||||
|
||||
18
src/screen.h
18
src/screen.h
@@ -62,6 +62,12 @@ typedef struct WAppIconChain {
|
||||
} WAppIconChain;
|
||||
|
||||
|
||||
/* Drawers, which are docks, really */
|
||||
typedef struct WDrawerChain {
|
||||
struct WDock *adrawer;
|
||||
struct WDrawerChain *next;
|
||||
} WDrawerChain;
|
||||
|
||||
/*
|
||||
* each WScreen is saved into a context associated with it's root window
|
||||
*/
|
||||
@@ -219,16 +225,22 @@ typedef struct _WScreen {
|
||||
struct WMenu *workspace_submenu; /* workspace list for window_menu */
|
||||
|
||||
struct WDock *dock; /* the application dock */
|
||||
struct WMenu *dock_pos_menu; /* Dock position menu */
|
||||
struct WPixmap *dock_dots; /* 3 dots for the Dock */
|
||||
Window dock_shadow; /* shadow for dock buttons */
|
||||
struct WAppIcon *clip_icon; /* The clip main icon */
|
||||
struct WAppIcon *clip_icon; /* The clip main icon, or the dock's, if they are merged */
|
||||
struct WMenu *clip_menu; /* Menu for clips */
|
||||
struct WMenu *clip_submenu; /* Workspace list for clips */
|
||||
struct WMenu *clip_options; /* Options for Clip */
|
||||
struct WMenu *clip_ws_menu; /* workspace menu for clip */
|
||||
struct WMenu *drawer_menu; /* Menu for drawers */
|
||||
struct WDock *last_dock;
|
||||
WAppIconChain *global_icons; /* for omnipresent icons chain in clip */
|
||||
int global_icon_count; /* How many global icons do we have */
|
||||
WDrawerChain *drawers; /* Chain of drawers */
|
||||
/* Cache the following two informations, as they are used quite a lot */
|
||||
int drawer_count; /* Nb of drawers that */
|
||||
struct WDock *attracting_drawer; /* The drawer that auto-attracts icons, or NULL */
|
||||
|
||||
int keymove_tick;
|
||||
struct RContext *rcontext; /* wrlib context */
|
||||
@@ -236,8 +248,8 @@ typedef struct _WScreen {
|
||||
WMScreen *wmscreen; /* for widget library */
|
||||
|
||||
struct RImage *icon_tile;
|
||||
struct RImage *clip_tile;
|
||||
|
||||
struct RImage *clip_tile; /* tile with arrows to change workspace */
|
||||
struct RImage *drawer_tile; /* tile for a drawer (tile + arrow) */
|
||||
Pixmap icon_tile_pixmap; /* For app supplied icons */
|
||||
|
||||
struct RImage *def_icon_rimage; /* Default RImage icon */
|
||||
|
||||
@@ -236,16 +236,28 @@ static WMPropList *makeWindowState(WWindow * wwin, WApplication * wapp)
|
||||
WMReleasePropList(shortcut);
|
||||
if (wapp && wapp->app_icon && wapp->app_icon->dock) {
|
||||
int i;
|
||||
char *name;
|
||||
char *name = NULL;
|
||||
if (wapp->app_icon->dock == scr->dock) {
|
||||
name = "Dock";
|
||||
} else {
|
||||
}
|
||||
if (name == NULL) // Try the clips
|
||||
{
|
||||
for (i = 0; i < scr->workspace_count; i++)
|
||||
if (scr->workspaces[i]->clip == wapp->app_icon->dock)
|
||||
break;
|
||||
assert(i < scr->workspace_count);
|
||||
/*n = i+1; */
|
||||
name = scr->workspaces[i]->name;
|
||||
if (i < scr->workspace_count)
|
||||
name = scr->workspaces[i]->name;
|
||||
}
|
||||
if (name == NULL) // Try the drawers
|
||||
{
|
||||
WDrawerChain *dc;
|
||||
for (dc = scr->drawers; dc != NULL; dc = dc->next)
|
||||
{
|
||||
if (dc->adrawer == wapp->app_icon->dock)
|
||||
break;
|
||||
}
|
||||
assert(dc != NULL);
|
||||
name = dc->adrawer->icon_array[0]->wm_instance;
|
||||
}
|
||||
dock = WMCreatePLString(name);
|
||||
WMPutInPLDictionary(win_state, sDock, dock);
|
||||
@@ -462,7 +474,9 @@ void wSessionRestoreState(WScreen *scr)
|
||||
if (sscanf(tmp, "%i", &n) != 1) {
|
||||
if (!strcasecmp(tmp, "DOCK")) {
|
||||
dock = scr->dock;
|
||||
} else {
|
||||
}
|
||||
if (dock == NULL) // Try the clips
|
||||
{
|
||||
for (j = 0; j < scr->workspace_count; j++) {
|
||||
if (strcmp(scr->workspaces[j]->name, tmp) == 0) {
|
||||
dock = scr->workspaces[j]->clip;
|
||||
@@ -470,6 +484,18 @@ void wSessionRestoreState(WScreen *scr)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dock == NULL) // Try the drawers
|
||||
{
|
||||
WDrawerChain *dc;
|
||||
for (dc = scr->drawers; dc != NULL; dc = dc->next)
|
||||
{
|
||||
if (strcmp(dc->adrawer->icon_array[0]->wm_instance, tmp) == 0)
|
||||
{
|
||||
dock = dc->adrawer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (n == 0) {
|
||||
dock = scr->dock;
|
||||
|
||||
@@ -747,6 +747,14 @@ void StartUp(Bool defaultScreenOnly)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* auto-launch apps in drawers */
|
||||
if (!wPreferences.flags.nodrawer) {
|
||||
WDrawerChain *dc;
|
||||
for (dc = wScreen[j]->drawers; dc; dc = dc->next) {
|
||||
wScreen[j]->last_dock = dc->adrawer;
|
||||
wDockDoAutoLaunch(dc->adrawer, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* go to workspace where we were before restart */
|
||||
|
||||
@@ -137,80 +137,6 @@ void DoKaboom(WScreen * scr, Window win, int x, int y)
|
||||
#endif /* NORMAL_ICON_KABOOM */
|
||||
}
|
||||
|
||||
Pixmap MakeGhostDock(WDock * dock, int sx, int dx, int y)
|
||||
{
|
||||
WScreen *scr = dock->screen_ptr;
|
||||
XImage *img;
|
||||
RImage *back, *dock_image;
|
||||
Pixmap pixmap;
|
||||
int i, virtual_tiles, h, j, n;
|
||||
unsigned long red_mask, green_mask, blue_mask;
|
||||
|
||||
virtual_tiles = 0;
|
||||
for (i = 0; i < dock->max_icons; i++) {
|
||||
if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex > virtual_tiles)
|
||||
virtual_tiles = dock->icon_array[i]->yindex;
|
||||
}
|
||||
virtual_tiles++;
|
||||
h = virtual_tiles * wPreferences.icon_size;
|
||||
h = (y + h > scr->scr_height) ? scr->scr_height - y : h;
|
||||
virtual_tiles = h / wPreferences.icon_size; /* The visible ones */
|
||||
if (h % wPreferences.icon_size)
|
||||
virtual_tiles++; /* There is one partially visible tile at end */
|
||||
|
||||
img = XGetImage(dpy, scr->root_win, dx, y, wPreferences.icon_size, h, AllPlanes, ZPixmap);
|
||||
if (!img)
|
||||
return None;
|
||||
|
||||
red_mask = img->red_mask;
|
||||
green_mask = img->green_mask;
|
||||
blue_mask = img->blue_mask;
|
||||
|
||||
back = RCreateImageFromXImage(scr->rcontext, img, NULL);
|
||||
XDestroyImage(img);
|
||||
if (!back) {
|
||||
return None;
|
||||
}
|
||||
|
||||
for (i = 0; i < dock->max_icons; i++) {
|
||||
if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex < virtual_tiles) {
|
||||
Pixmap which;
|
||||
j = dock->icon_array[i]->yindex * wPreferences.icon_size;
|
||||
n = (h - j < wPreferences.icon_size) ? h - j : wPreferences.icon_size;
|
||||
if (dock->icon_array[i]->icon->pixmap)
|
||||
which = dock->icon_array[i]->icon->pixmap;
|
||||
else
|
||||
which = dock->icon_array[i]->icon->core->window;
|
||||
|
||||
img = XGetImage(dpy, which, 0, 0, wPreferences.icon_size, n, AllPlanes, ZPixmap);
|
||||
|
||||
if (!img) {
|
||||
RReleaseImage(back);
|
||||
return None;
|
||||
}
|
||||
img->red_mask = red_mask;
|
||||
img->green_mask = green_mask;
|
||||
img->blue_mask = blue_mask;
|
||||
|
||||
dock_image = RCreateImageFromXImage(scr->rcontext, img, NULL);
|
||||
XDestroyImage(img);
|
||||
if (!dock_image) {
|
||||
RReleaseImage(back);
|
||||
return None;
|
||||
}
|
||||
RCombineAreaWithOpaqueness(back, dock_image, 0, 0,
|
||||
wPreferences.icon_size, n, 0, j, 30 * 256 / 100);
|
||||
RReleaseImage(dock_image);
|
||||
}
|
||||
}
|
||||
|
||||
RConvertImage(scr->rcontext, back, &pixmap);
|
||||
|
||||
RReleaseImage(back);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
Pixmap MakeGhostIcon(WScreen * scr, Drawable drawable)
|
||||
{
|
||||
RImage *back;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "dock.h"
|
||||
|
||||
void DoKaboom(WScreen *scr, Window win, int x, int y);
|
||||
Pixmap MakeGhostDock(WDock *dock, int sx, int dx, int y);
|
||||
Pixmap MakeGhostIcon(WScreen *scr, Drawable drawable);
|
||||
void DoWindowBirth(WWindow *wwin);
|
||||
#endif
|
||||
|
||||
@@ -301,20 +301,6 @@
|
||||
* a docked icon must be dragged out to detach it */
|
||||
#define DOCK_DETTACH_THRESHOLD 3
|
||||
|
||||
/* Delay (in ms) after which the clip will autocollapse when leaved */
|
||||
#define AUTO_COLLAPSE_DELAY 1000
|
||||
|
||||
/* Delay (in ms) after which the clip will autoexpand when entered.
|
||||
* Set this to zero if you want instant expanding. */
|
||||
#define AUTO_EXPAND_DELAY 600
|
||||
|
||||
/* Delay (in ms) after which the clip will be lowered when leaved */
|
||||
#define AUTO_LOWER_DELAY 1000
|
||||
|
||||
/* Delay (in ms) after which the clip will be raised when entered.
|
||||
* Set this to zero if you want instant raise. */
|
||||
#define AUTO_RAISE_DELAY 600
|
||||
|
||||
/* Max. number of icons the dock and clip can have */
|
||||
#define DOCK_MAX_ICONS 32
|
||||
|
||||
@@ -329,7 +315,7 @@
|
||||
|
||||
#define MAX_WORKSPACENAME_WIDTH 64
|
||||
/* max width of window title in window list */
|
||||
#define MAX_WINDOWLIST_WIDTH 160
|
||||
#define MAX_WINDOWLIST_WIDTH 400
|
||||
|
||||
#ifndef HAVE_INOTIFY
|
||||
/* Check defaults database for changes every this many milliseconds */
|
||||
|
||||
@@ -597,6 +597,37 @@ void wDefaultChangeIcon(WScreen * scr, char *instance, char *class, char *file)
|
||||
WMPLSetCaseSensitive(False);
|
||||
}
|
||||
|
||||
void wDefaultPurgeInfo(WScreen *scr, char *instance, char *class)
|
||||
{
|
||||
WMPropList *value, *key, *dict;
|
||||
char *buffer;
|
||||
|
||||
if (!AIcon) { /* Unnecessary precaution */
|
||||
init_wdefaults();
|
||||
}
|
||||
|
||||
WMPLSetCaseSensitive(True);
|
||||
|
||||
buffer = wmalloc(strlen(class) + strlen(instance) + 2);
|
||||
sprintf(buffer, "%s.%s", instance, class);
|
||||
key = WMCreatePLString(buffer);
|
||||
|
||||
dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key);
|
||||
|
||||
if (dict) {
|
||||
value = WMGetFromPLDictionary(dict, AIcon);
|
||||
if (value) {
|
||||
WMRemoveFromPLDictionary(dict, AIcon);
|
||||
}
|
||||
WMRemoveFromPLDictionary(WDWindowAttributes->dictionary, key);
|
||||
UpdateDomainFile(WDWindowAttributes);
|
||||
}
|
||||
|
||||
wfree(buffer);
|
||||
WMReleasePropList(key);
|
||||
WMPLSetCaseSensitive(False);
|
||||
}
|
||||
|
||||
/* --------------------------- Local ----------------------- */
|
||||
|
||||
static int getBool(WMPropList * key, WMPropList * value)
|
||||
|
||||
@@ -103,7 +103,7 @@ int wWorkspaceNew(WScreen *scr)
|
||||
}
|
||||
|
||||
if (!wPreferences.flags.noclip)
|
||||
wspace->clip = wDockCreate(scr, WM_CLIP);
|
||||
wspace->clip = wDockCreate(scr, WM_CLIP, NULL);
|
||||
|
||||
list = wmalloc(sizeof(WWorkspace *) * scr->workspace_count);
|
||||
|
||||
@@ -471,6 +471,8 @@ void wWorkspaceRelativeChange(WScreen * scr, int amount)
|
||||
void wWorkspaceForceChange(WScreen * scr, int workspace)
|
||||
{
|
||||
WWindow *tmp, *foc = NULL, *foc2 = NULL;
|
||||
WWindow **toUnmap;
|
||||
int toUnmapSize, toUnmapCount;
|
||||
|
||||
if (workspace >= MAX_WORKSPACES || workspace < 0)
|
||||
return;
|
||||
@@ -490,6 +492,10 @@ void wWorkspaceForceChange(WScreen * scr, int workspace)
|
||||
|
||||
wWorkspaceMenuUpdate(scr, scr->clip_ws_menu);
|
||||
|
||||
toUnmapSize = 16;
|
||||
toUnmapCount = 0;
|
||||
toUnmap = wmalloc(toUnmapSize * sizeof(WWindow *));
|
||||
|
||||
if ((tmp = scr->focused_window) != NULL) {
|
||||
if ((IS_OMNIPRESENT(tmp) && (tmp->flags.mapped || tmp->flags.shaded) &&
|
||||
!WFLAGP(tmp, no_focusable)) || tmp->flags.changing_workspace) {
|
||||
@@ -504,7 +510,12 @@ void wWorkspaceForceChange(WScreen * scr, int workspace)
|
||||
/* unmap windows not on this workspace */
|
||||
if ((tmp->flags.mapped || tmp->flags.shaded) &&
|
||||
!IS_OMNIPRESENT(tmp) && !tmp->flags.changing_workspace) {
|
||||
wWindowUnmap(tmp);
|
||||
if (toUnmapCount == toUnmapSize)
|
||||
{
|
||||
toUnmapSize *= 2;
|
||||
toUnmap = wrealloc(toUnmap, toUnmapSize * sizeof(WWindow *));
|
||||
}
|
||||
toUnmap[toUnmapCount++] = tmp;
|
||||
}
|
||||
/* also unmap miniwindows not on this workspace */
|
||||
if (!wPreferences.sticky_icons && tmp->flags.miniaturized &&
|
||||
@@ -553,6 +564,12 @@ void wWorkspaceForceChange(WScreen * scr, int workspace)
|
||||
tmp = tmp->prev;
|
||||
}
|
||||
|
||||
while (toUnmapCount > 0)
|
||||
{
|
||||
wWindowUnmap(toUnmap[--toUnmapCount]);
|
||||
}
|
||||
wfree(toUnmap);
|
||||
|
||||
/* Gobble up events unleashed by our mapping & unmapping.
|
||||
* These may trigger various grab-initiated focus &
|
||||
* crossing events. However, we don't care about them,
|
||||
@@ -606,15 +623,14 @@ void wWorkspaceForceChange(WScreen * scr, int workspace)
|
||||
if (scr->dock)
|
||||
wAppIconPaint(scr->dock->icon_array[0]);
|
||||
|
||||
if (scr->clip_icon) {
|
||||
if (scr->workspaces[workspace]->clip->auto_collapse ||
|
||||
scr->workspaces[workspace]->clip->auto_raise_lower) {
|
||||
/* to handle enter notify. This will also */
|
||||
XUnmapWindow(dpy, scr->clip_icon->icon->core->window);
|
||||
XMapWindow(dpy, scr->clip_icon->icon->core->window);
|
||||
} else {
|
||||
wClipIconPaint(scr->clip_icon);
|
||||
}
|
||||
if (!wPreferences.flags.noclip && (scr->workspaces[workspace]->clip->auto_collapse ||
|
||||
scr->workspaces[workspace]->clip->auto_raise_lower)) {
|
||||
/* to handle enter notify. This will also */
|
||||
XUnmapWindow(dpy, scr->clip_icon->icon->core->window);
|
||||
XMapWindow(dpy, scr->clip_icon->icon->core->window);
|
||||
}
|
||||
else if (scr->clip_icon != NULL) {
|
||||
wClipIconPaint(scr->clip_icon);
|
||||
}
|
||||
wScreenUpdateUsableArea(scr);
|
||||
wNETWMUpdateDesktop(scr);
|
||||
|
||||
Reference in New Issue
Block a user