mirror of
https://github.com/gryf/wmaker.git
synced 2026-04-09 17:33:32 +02:00
wmaker: add directional window focus
This patch is adding directional window focus (like in openbox), where the focus can be passed to the current window neighboors with a shortcut key. Comparisons are performed using window centres. New options are FocusWindowLeftKey, FocusWindowRightKey, FocusWindowUpKey, FocusWindowDownKey. Other WM are setting those to SUPER+LEFT/RIGHT/UP/DOWN keys but currently those are not set by default. CirculateRaise option which is described in WPrefs as 'Raise window when switching focus with keyboard' is also used to raise/not raise windows that are fully covered by other windows.
This commit is contained in:
committed by
Carlos R. Mafra
parent
a3c02a22bd
commit
33fba87ed1
@@ -240,6 +240,100 @@ void wSetFocusTo(WScreen *scr, WWindow *wwin)
|
||||
old_scr = scr;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* wSetFocusToDirection--
|
||||
* Moves focus to the nearest window in the given cardinal
|
||||
* direction (DIRECTION_LEFT, DIRECTION_RIGHT, DIRECTION_UP,
|
||||
* DIRECTION_DOWN from xinerama.h).
|
||||
*
|
||||
* Selection algorithm: candidate windows are scored by
|
||||
* (primary_distance + perpendicular_offset). A large penalty is
|
||||
* added when the perpendicular offset exceeds the primary distance
|
||||
* (i.e. the candidate is more than 45 degrees off-axis). The window
|
||||
* with the lowest score wins. If no candidate exists in the requested
|
||||
* direction the call is silently ignored.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
void wSetFocusToDirection(WScreen *scr, int direction)
|
||||
{
|
||||
WWindow *focused = scr->focused_window;
|
||||
WWindow *best = NULL;
|
||||
WWindow *candidate = NULL;
|
||||
int my_cx, my_cy;
|
||||
long best_score = -1;
|
||||
|
||||
if (!focused || !focused->flags.mapped)
|
||||
return;
|
||||
|
||||
/* centre of the focused window */
|
||||
my_cx = focused->frame_x + (int)focused->frame->core->width / 2;
|
||||
my_cy = focused->frame_y + (int)focused->frame->core->height / 2;
|
||||
|
||||
/* Iterate from most-recently-focused to least-recently-focused */
|
||||
for (candidate = focused->prev; candidate != NULL; candidate = candidate->prev) {
|
||||
int his_cx, his_cy, distance, offset;
|
||||
long score;
|
||||
|
||||
if (!candidate->flags.mapped)
|
||||
continue;
|
||||
if (WFLAGP(candidate, no_focusable))
|
||||
continue;
|
||||
if (!candidate->frame || candidate->frame->workspace != scr->current_workspace)
|
||||
continue;
|
||||
|
||||
/* ignore fully covered windows if cannot raised them */
|
||||
if (!wPreferences.circ_raise && wWindowIsFullyCovered(candidate))
|
||||
continue;
|
||||
|
||||
/* relative centre of candidate */
|
||||
his_cx = (candidate->frame_x - my_cx) + (int)candidate->frame->core->width / 2;
|
||||
his_cy = (candidate->frame_y - my_cy) + (int)candidate->frame->core->height / 2;
|
||||
|
||||
switch (direction) {
|
||||
case DIRECTION_RIGHT:
|
||||
distance = his_cx;
|
||||
offset = his_cy < 0 ? -his_cy : his_cy;
|
||||
break;
|
||||
case DIRECTION_LEFT:
|
||||
distance = -his_cx;
|
||||
offset = his_cy < 0 ? -his_cy : his_cy;
|
||||
break;
|
||||
case DIRECTION_DOWN:
|
||||
distance = his_cy;
|
||||
offset = his_cx < 0 ? -his_cx : his_cx;
|
||||
break;
|
||||
case DIRECTION_UP:
|
||||
distance = -his_cy;
|
||||
offset = his_cx < 0 ? -his_cx : his_cx;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
/* candidate must be strictly in the requested direction */
|
||||
if (distance <= 0)
|
||||
continue;
|
||||
|
||||
score = distance + offset;
|
||||
|
||||
/* heavy penalty for windows more than 45 degrees off-axis */
|
||||
if (offset > distance)
|
||||
score += 1000000L;
|
||||
|
||||
if (best_score < 0 || score < best_score) {
|
||||
best = candidate;
|
||||
best_score = score;
|
||||
}
|
||||
}
|
||||
|
||||
if (best) {
|
||||
if (wPreferences.circ_raise)
|
||||
wRaiseFrame(best->frame->core);
|
||||
wSetFocusTo(scr, best);
|
||||
}
|
||||
}
|
||||
|
||||
void wShadeWindow(WWindow *wwin)
|
||||
{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user