in progress improved window cmd-tab switching

This commit is contained in:
Mike Small 2022-08-14 13:27:30 -04:00
parent 39038bddb6
commit f4d595988a
11 changed files with 1340 additions and 1349 deletions

View File

@ -1,3 +1,35 @@
2022-01-09 Mike Small <smallm@sdf.org>
First step to more Windows like alt-tab window selection.
(In this case alt is mod4 key instead later to be configurable.)
Also hard code the binding as a step towards more limited
configuration and more fixed behavior...
* src/menus.cc (ExecuteFunction): Change F_WARPRING function
to HF_WARPRING to make clear its only used in hard coded commands
not from config. Add handling of "reverse" argument to mean to warp
along the ring in the reverse order from last key press.
(HardCodeSomeKeys): hard coded bindings for mod4-tab, mod4-left,
and mod4-right. Should make the modifier key customizable later.
* src/gram.y: Remove parsing logic for F_WARPRING.
* src/menus.cc (ExecuteFunction): Remove uses of F_WARPNEXT and
F_WARPPREV in ExecuteFunction and code for doing this kind of warp.
Keep F_WARPRING
* src/events.c (HandleButtonRelease): Remove F_CIRCLE{UP,DOWN} as
causes for PopDownMenu() call. Still needed by F_REFRESH.
* src/menus.cc (ExecuteFunction): Remove calls to
XCirculateSubwindows{Up,Down} corresponding to F_CIRCLE{UP,DOWN}.
* src/parse.h (F_CIRCLEUP): remove F_CIRCLEUP, F_CIRCLEDOWN,
F_WARPNEXT, F_WARPPREV, F_WARPRING tokens.
* src/parse.c (keytable): remove f.circleup, f.circledown,
f.warpnext, f.warpprev, f.warpring as configure file
keywords.
2021-04-03 Mike Small <smallm@sdf.org>
* src/parse.c (keytable): remove function keyword form parse table

8
README
View File

@ -11,6 +11,11 @@ Features removed...
3. default user defined functions: move-or-lower, move-or-raise,
and move-or-iconify (changed to builtins) and the ability to define
user defined functions.
4. f.CircleUp, f.CircleDown, f.warpnext, f.warpprev. f.warpring continues
to exist but can take no custom binding. Bindings for f.warpring "prev"
and f.warpring "next" are hardcode on mod4-Left and mod4-Right. A
new mod4-tab command is hardcoded to reverse the warpring order argument
with each use.
Changes ...
@ -21,6 +26,9 @@ Changes ...
Additions ...
1. builtin functions: move-or-lower, move-or-raise, and move-or-iconify.
2. mod4-tab (modifier should be customizable at some point) cycles windows
like MS Windows alt-tab, reversing the order of f.warpring each use to
make it easy to flip back and forth between two windows.
The master development code repository can be found at:

View File

@ -1550,8 +1550,6 @@ HandleButtonRelease(void)
case F_WARPTOSCREEN:
XUngrabPointer(dpy, CurrentTime);
/* fall through */
case F_CIRCLEUP:
case F_CIRCLEDOWN:
case F_REFRESH:
PopDownMenu();
break;

2270
src/gram.c

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* A Bison parser, made by GNU Bison 3.7.6. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -15,7 +16,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@ -30,6 +31,10 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
#ifndef YY_YY_GRAM_H_INCLUDED
# define YY_YY_GRAM_H_INCLUDED
/* Debug traces. */
@ -40,70 +45,79 @@
extern int yydebug;
#endif
/* Token type. */
/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
LB = 258,
RB = 259,
LP = 260,
RP = 261,
MENUS = 262,
MENU = 263,
BUTTON = 264,
DEFAULT_FUNCTION = 265,
PLUS = 266,
MINUS = 267,
ALL = 268,
OR = 269,
CURSORS = 270,
ICONS = 271,
COLOR = 272,
SAVECOLOR = 273,
MONOCHROME = 274,
WINDOW_FUNCTION = 276,
MAKE_TITLE = 277,
GRAYSCALE = 278,
NO_TITLE = 279,
AUTO_RAISE = 280,
META = 281,
SHIFT = 282,
LOCK = 283,
CONTROL = 284,
WINDOW = 285,
TITLE = 286,
ICON = 287,
ROOT = 288,
FRAME = 289,
COLON = 290,
EQUALS = 291,
START_ICONIFIED = 292,
MOVE = 293,
RESIZE = 294,
WAIT = 295,
SELECT = 296,
KILL = 297,
LEFT_TITLEBUTTON = 298,
RIGHT_TITLEBUTTON = 299,
NUMBER = 300,
KEYWORD = 301,
NKEYWORD = 302,
CKEYWORD = 303,
CLKEYWORD = 304,
FKEYWORD = 305,
FSKEYWORD = 306,
SKEYWORD = 307,
DKEYWORD = 308,
JKEYWORD = 309,
WINDOW_RING = 310,
WARP_CURSOR = 311,
ERRORTOKEN = 312,
NO_STACKMODE = 313,
STRING = 314
YYEMPTY = -2,
YYEOF = 0, /* "end of file" */
YYerror = 256, /* error */
YYUNDEF = 257, /* "invalid token" */
LB = 258, /* LB */
RB = 259, /* RB */
LP = 260, /* LP */
RP = 261, /* RP */
MENUS = 262, /* MENUS */
MENU = 263, /* MENU */
BUTTON = 264, /* BUTTON */
DEFAULT_FUNCTION = 265, /* DEFAULT_FUNCTION */
PLUS = 266, /* PLUS */
MINUS = 267, /* MINUS */
ALL = 268, /* ALL */
OR = 269, /* OR */
CURSORS = 270, /* CURSORS */
ICONS = 271, /* ICONS */
COLOR = 272, /* COLOR */
SAVECOLOR = 273, /* SAVECOLOR */
MONOCHROME = 274, /* MONOCHROME */
WINDOW_FUNCTION = 275, /* WINDOW_FUNCTION */
MAKE_TITLE = 276, /* MAKE_TITLE */
GRAYSCALE = 277, /* GRAYSCALE */
NO_TITLE = 278, /* NO_TITLE */
AUTO_RAISE = 279, /* AUTO_RAISE */
META = 280, /* META */
SHIFT = 281, /* SHIFT */
LOCK = 282, /* LOCK */
CONTROL = 283, /* CONTROL */
WINDOW = 284, /* WINDOW */
TITLE = 285, /* TITLE */
ICON = 286, /* ICON */
ROOT = 287, /* ROOT */
FRAME = 288, /* FRAME */
COLON = 289, /* COLON */
EQUALS = 290, /* EQUALS */
START_ICONIFIED = 291, /* START_ICONIFIED */
MOVE = 292, /* MOVE */
RESIZE = 293, /* RESIZE */
WAIT = 294, /* WAIT */
SELECT = 295, /* SELECT */
KILL = 296, /* KILL */
LEFT_TITLEBUTTON = 297, /* LEFT_TITLEBUTTON */
RIGHT_TITLEBUTTON = 298, /* RIGHT_TITLEBUTTON */
NUMBER = 299, /* NUMBER */
KEYWORD = 300, /* KEYWORD */
NKEYWORD = 301, /* NKEYWORD */
CKEYWORD = 302, /* CKEYWORD */
CLKEYWORD = 303, /* CLKEYWORD */
FKEYWORD = 304, /* FKEYWORD */
FSKEYWORD = 305, /* FSKEYWORD */
SKEYWORD = 306, /* SKEYWORD */
DKEYWORD = 307, /* DKEYWORD */
JKEYWORD = 308, /* JKEYWORD */
WINDOW_RING = 309, /* WINDOW_RING */
WARP_CURSOR = 310, /* WARP_CURSOR */
ERRORTOKEN = 311, /* ERRORTOKEN */
NO_STACKMODE = 312, /* NO_STACKMODE */
STRING = 313 /* STRING */
};
typedef enum yytokentype yytoken_kind_t;
#endif
/* Tokens. */
/* Token kinds. */
#define YYEMPTY -2
#define YYEOF 0
#define YYerror 256
#define YYUNDEF 257
#define LB 258
#define RB 259
#define LP 260
@ -121,59 +135,58 @@ extern int yydebug;
#define COLOR 272
#define SAVECOLOR 273
#define MONOCHROME 274
#define WINDOW_FUNCTION 276
#define MAKE_TITLE 277
#define GRAYSCALE 278
#define NO_TITLE 279
#define AUTO_RAISE 280
#define META 281
#define SHIFT 282
#define LOCK 283
#define CONTROL 284
#define WINDOW 285
#define TITLE 286
#define ICON 287
#define ROOT 288
#define FRAME 289
#define COLON 290
#define EQUALS 291
#define START_ICONIFIED 292
#define MOVE 293
#define RESIZE 294
#define WAIT 295
#define SELECT 296
#define KILL 297
#define LEFT_TITLEBUTTON 298
#define RIGHT_TITLEBUTTON 299
#define NUMBER 300
#define KEYWORD 301
#define NKEYWORD 302
#define CKEYWORD 303
#define CLKEYWORD 304
#define FKEYWORD 305
#define FSKEYWORD 306
#define SKEYWORD 307
#define DKEYWORD 308
#define JKEYWORD 309
#define WINDOW_RING 310
#define WARP_CURSOR 311
#define ERRORTOKEN 312
#define NO_STACKMODE 313
#define STRING 314
#define WINDOW_FUNCTION 275
#define MAKE_TITLE 276
#define GRAYSCALE 277
#define NO_TITLE 278
#define AUTO_RAISE 279
#define META 280
#define SHIFT 281
#define LOCK 282
#define CONTROL 283
#define WINDOW 284
#define TITLE 285
#define ICON 286
#define ROOT 287
#define FRAME 288
#define COLON 289
#define EQUALS 290
#define START_ICONIFIED 291
#define MOVE 292
#define RESIZE 293
#define WAIT 294
#define SELECT 295
#define KILL 296
#define LEFT_TITLEBUTTON 297
#define RIGHT_TITLEBUTTON 298
#define NUMBER 299
#define KEYWORD 300
#define NKEYWORD 301
#define CKEYWORD 302
#define CLKEYWORD 303
#define FKEYWORD 304
#define FSKEYWORD 305
#define SKEYWORD 306
#define DKEYWORD 307
#define JKEYWORD 308
#define WINDOW_RING 309
#define WARP_CURSOR 310
#define ERRORTOKEN 311
#define NO_STACKMODE 312
#define STRING 313
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
#line 106 "gram.y" /* yacc.c:1909 */
#line 106 "gram.y"
int num;
char *ptr;
#line 177 "gram.h" /* yacc.c:1909 */
};
#line 188 "gram.h"
};
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1

View File

@ -480,14 +480,6 @@ action : FKEYWORD { $$ = $1; }
pull = GetRoot ($2, NULLSTR,NULLSTR);
pull->prev = root;
break;
case F_WARPRING:
if (!CheckWarpRingArg (Action)) {
twmrc_error_prefix();
fprintf (stderr,
"ignoring invalid f.warptoring argument \"%s\"\n",
Action);
$$ = F_NOP;
}
case F_WARPTOSCREEN:
if (!CheckWarpScreenArg (Action)) {
twmrc_error_prefix();

View File

@ -65,6 +65,7 @@ in this Software without prior written authorization from The Open Group.
#include <algorithm>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <X11/Xos.h>
#include "twm.h"
@ -157,7 +158,11 @@ InitMenus(void)
{
for (key = Scr->FuncKeyRoot.next; key != NULL;)
{
free(key->name);
// This is a problem. In HardCodeSomeKeys() you're adding
// string literals in as key->name. Should change the
// structure to take string, but not in next checkin.
// Will have to change that code to strdup the literals.
free(const_cast<void*>(static_cast<const void*>(key->name)));
tmp = key;
key = key->next;
free(tmp);
@ -179,8 +184,8 @@ InitMenus(void)
* \param win_name the window name (if any)
* \param action the action string associated with the function (if any)
*/
Bool AddFuncKey (char *name, int cont, int mods, int func, char *win_name,
char *action)
Bool AddFuncKey(const char *name, int cont, int mods, int func,
const char *win_name, const char *action)
{
FuncKey *fkey;
KeySym keysym;
@ -205,9 +210,14 @@ Bool AddFuncKey (char *name, int cont, int mods, int func, char *win_name,
break;
}
if (fkey == NULL)
if (fkey == nullptr)
{
fkey = new FuncKey;
// This might be passed to free() still. See InitMenus() above.
fkey = static_cast<FuncKey*>(malloc(sizeof(FuncKey)));
if (!fkey) {
std::cerr << "Out of memory in AddFuncKey().\n";
exit(1);
}
fkey->next = Scr->FuncKeyRoot.next;
Scr->FuncKeyRoot.next = fkey;
}
@ -224,6 +234,39 @@ Bool AddFuncKey (char *name, int cont, int mods, int func, char *win_name,
return True;
}
const int HF_WARPRING = 500;
struct HCKey {
const char* name;
int cont;
int func;
const char* action;
};
void HardCodeSomeKeys(int mods)
{
std::vector<HCKey> keys {
{ "Tab", C_WINDOW, HF_WARPRING, "reverse"},
{ "Left", C_WINDOW, HF_WARPRING, "prev"},
{ "Right", C_WINDOW, HF_WARPRING, "next"}
};
// The loop below will be inadequate if you ever use ORed context bits.
// See GotKey() in gram.y.
for (auto& k : keys) {
// TODO: push this into AddFuncKey, also see use in gram.y.
// maybe change to std::string in FuncKey struct and remove frees, mallocs.
// Now we can't give a pointer to string literal cause free() might be called on it.
const char* nm = strdup(k.name);
if (!nm) {
std::cerr << "Out of memory in HardCodeSomeKeys().\n";
exit(1);
}
if (!AddFuncKey(nm, k.cont, mods, k.func, nullptr, k.action))
std::cerr << "Failed to hard code key " << k.name << " to action "
<< k.func << " with argument " << k.action << '\n';
}
}
int CreateTitleButton(const char *name, int func, const char *action,
@ -1272,9 +1315,7 @@ ExecuteFunction(int func, const char *action, Window w, TwmWindow *tmp_win,
case F_RAISELOWER:
case F_WARPTOSCREEN:
case F_WARPTO:
case F_WARPRING:
case F_WARPNEXT:
case F_WARPPREV:
case HF_WARPRING:
case F_COLORMAP:
break;
default:
@ -1819,14 +1860,6 @@ ExecuteFunction(int func, const char *action, Window w, TwmWindow *tmp_win,
Bell(XkbBI_MinorError,0,tmp_win->w);
break;
case F_CIRCLEUP:
XCirculateSubwindowsUp(dpy, Scr->Root);
break;
case F_CIRCLEDOWN:
XCirculateSubwindowsDown(dpy, Scr->Root);
break;
case F_EXEC:
PopDownMenu();
Execute(action);
@ -1897,40 +1930,6 @@ ExecuteFunction(int func, const char *action, Window w, TwmWindow *tmp_win,
}
break;
case F_WARPPREV:
case F_WARPNEXT:
{
TwmWindow* t;
static TwmWindow* savedwarp{nullptr};
TwmWindow *of, *l, *n;
int c{0};
#define wseq(w) (func == F_WARPNEXT ? (w)->next : (w)->prev)
#define nwin(w) ((w) && (n=wseq(w)) != NULL && n != &Scr->TwmRoot ? n : l)
#define bwin(w) (!(w)||(w)==of||!(Scr->WarpUnmapped||(w)->mapped))
of=(Scr->Focus ? Scr->Focus : &Scr->TwmRoot);
for(t=Scr->TwmRoot.next; t; t=t->next) if(!bwin(t)) break;
if(!t) break; /* no windows we can use */
if(func == F_WARPPREV) for(l=of; l->next; l=l->next) ;
else l = Scr->TwmRoot.next;
for(t=of; bwin(t) && c < 2; t=nwin(t)) if(t == of) c++;
if(bwin(t) || c >= 2) Bell(XkbBI_MinorError,0,None);
else {
if(of && of == savedwarp) {
Iconify(of, 0, 0);
savedwarp = NULL;
}
if(!t->mapped) savedwarp = t; else savedwarp = NULL;
WarpThere(t);
}
break;
}
case F_WARPTO:
{
const size_t len{strlen(action)};
@ -1958,14 +1957,18 @@ ExecuteFunction(int func, const char *action, Window w, TwmWindow *tmp_win,
}
break;
case F_WARPRING:
case HF_WARPRING:
switch (action[0]) {
static int direction = True; // True means "next".
case 'n':
WarpAlongRing (&eventp->xbutton, True);
WarpAlongRing(&eventp->xbutton, True);
break;
case 'p':
WarpAlongRing (&eventp->xbutton, False);
WarpAlongRing(&eventp->xbutton, False);
break;
case 'r':
WarpAlongRing(&eventp->xbutton, direction);
direction = !direction;
default:
Bell(XkbBI_MinorError,0,None);
break;

View File

@ -122,14 +122,14 @@ typedef struct MouseButton
typedef struct FuncKey
{
struct FuncKey *next; /* next in the list of function keys */
char *name; /* key name */
const char *name; /* key name */
KeySym keysym; /* X keysym */
KeyCode keycode; /* X keycode */
int cont; /* context */
int mods; /* modifiers */
int func; /* function to perform */
char *win_name; /* window name (if any) */
char *action; /* action string (if any) */
const char *win_name; /* window name (if any) */
const char *action; /* action string (if any) */
} FuncKey;
extern int RootFunction;
@ -171,7 +171,9 @@ extern int MenuDepth;
#endif
EXTERN void InitMenus( void );
EXTERN Bool AddFuncKey( char *name, int cont, int mods, int func, char *win_name, char *action );
EXTERN Bool AddFuncKey( const char *name, int cont, int mods, int func,
const char *win_name, const char *action );
EXTERN void HardCodeSomeKeys(int mods);
EXTERN int CreateTitleButton( const char *name, int func, const char *action, MenuRoot *menuroot, Bool rightside, Bool append );
EXTERN void InitTitlebarButtons( void );
EXTERN void PaintEntry( MenuRoot *mr, MenuItem *mi, int exposure );

View File

@ -155,7 +155,7 @@ static int doparse (int (*ifunc)(void),
}
int ParseTwmrc (char *filename)
int ParseTwmrc(char *filename)
{
int i;
char *home = NULL;
@ -205,18 +205,18 @@ int ParseTwmrc (char *filename)
int status;
if (filename && cp != filename) {
fprintf (stderr,
"%s: unable to open twmrc file %s, using %s instead\n",
ProgramName, filename, cp);
fprintf(stderr,
"%s: unable to open twmrc file %s, using %s instead\n",
ProgramName, filename, cp);
}
status = doparse (twmFileInput, "file", cp);
fclose (twmrc);
status = doparse(twmFileInput, "file", cp);
fclose(twmrc);
return status;
} else {
if (filename) {
fprintf (stderr,
fprintf(stderr,
"%s: unable to open twmrc file %s, using built-in defaults instead\n",
ProgramName, filename);
ProgramName, filename);
}
return ParseStringList (defTwmrc);
}
@ -392,8 +392,6 @@ static TwmKeyword keytable[] = {
{ "f.autoraise", FKEYWORD, F_AUTORAISE },
{ "f.beep", FKEYWORD, F_BEEP },
{ "f.bottomzoom", FKEYWORD, F_BOTTOMZOOM },
{ "f.circledown", FKEYWORD, F_CIRCLEDOWN },
{ "f.circleup", FKEYWORD, F_CIRCLEUP },
{ "f.colormap", FSKEYWORD, F_COLORMAP },
{ "f.cut", FSKEYWORD, F_CUT },
{ "f.cutfile", FKEYWORD, F_CUTFILE },
@ -437,9 +435,6 @@ static TwmKeyword keytable[] = {
{ "f.version", FKEYWORD, F_VERSION },
{ "f.vlzoom", FKEYWORD, F_LEFTZOOM },
{ "f.vrzoom", FKEYWORD, F_RIGHTZOOM },
{ "f.warpnext", FKEYWORD, F_WARPNEXT },
{ "f.warpprev", FKEYWORD, F_WARPPREV },
{ "f.warpring", FSKEYWORD, F_WARPRING },
{ "f.warpto", FSKEYWORD, F_WARPTO },
{ "f.warptoscreen", FSKEYWORD, F_WARPTOSCREEN },
{ "f.winrefresh", FKEYWORD, F_WINREFRESH },

View File

@ -114,8 +114,6 @@ extern int mods;
#define F_SAVEYOURSELF 29
#define F_VERSION 30
#define F_TITLE 31
#define F_CIRCLEUP 41
#define F_CIRCLEDOWN 42
#define F_CUTFILE 43
#define F_SHOWLIST 44
#define F_HIDELIST 45
@ -124,10 +122,7 @@ extern int mods;
#define F_MOVE_OR_RAISE 48
#define F_MENU 101 /* string */
#define F_WARPNEXT 112 /* string */
#define F_WARPPREV 113 /* string */
#define F_WARPTO 102 /* string */
#define F_WARPRING 104 /* string */
#define F_FILE 105 /* string */
#define F_EXEC 106 /* string */
#define F_CUT 107 /* string */

View File

@ -533,6 +533,9 @@ main(int argc, char *argv[])
if (!Scr->HaveFonts) CreateFonts();
CreateGCs();
MakeMenus();
// TODO: make this configurable.
const int default_key_mods = Mod4Mask;
HardCodeSomeKeys(default_key_mods);
Scr->TitleBarFont.y += Scr->FramePadding;
Scr->TitleHeight = Scr->TitleBarFont.height + Scr->FramePadding * 2;