⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 focus.c

📁 具有IDE功能的编辑器
💻 C
字号:
/* focus.c - records a history of focusses for reverting focus, also does focus cycling   Copyright (C) 1996-2000 Paul Sheer   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   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   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, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307, USA. */#include <config.h>#include <stdio.h>#include <my_string.h>#include <stdlib.h>#include <stdarg.h>#include <X11/Intrinsic.h>#include "stringtools.h"#include "app_glob.c"#include "coolwidget.h"#include "coollocal.h"#include "mad.h"/* Focus stack: This stack remembers the focus historyso that when widgets are destroyed, the focus returns tothe most recent widget in the history. This is equivalentto the revert_to in the XSetInputFocus() function,however XSetInputFocus() has an effective history ofonly one.The commands to change focus are CFocus(CWidget *w)*/extern struct look *look;#define FOCUS_STACK_SIZE 128static Window focus_stack[FOCUS_STACK_SIZE];static int focus_sp = 0;static Window current_focus = -1;static Window current_ic_focus = -1;static Window dnd_focus = -1;void save_current_focus_for_dnd (Window new_focus){    dnd_focus = current_focus;    current_focus = new_focus;}void restore_current_focus_for_dnd (void){    current_focus = dnd_focus;}void add_to_focus_stack (Window w){    int i;    i = focus_sp;    while (i--)	if (focus_stack[i] == w) {	    focus_sp = i + 1;	    return;	}    if (focus_sp >= FOCUS_STACK_SIZE) {#ifdef FOCUS_DEBUG/* NLS ? */	printf ("add_to_focus_stack(): focus_sp overflow\n");#endif	return;    }    focus_stack[focus_sp++] = w;#ifdef FOCUS_DEBUG/* NLS ? */    printf ("add_to_focus_stack(%x): focus_sp = %d\n", (unsigned int) w, focus_sp);#endif}void focus_stack_remove_window (Window w){    int i;    i = focus_sp;    while (i--)	if (focus_stack[i] == w) {	    focus_stack[i] = 0;	    while (focus_sp && !focus_stack[focus_sp - 1])		focus_sp--;#ifdef FOCUS_DEBUG/* NLS ? */    printf ("focus_stack_remove_window(): focus_sp = %d\n", focus_sp);#endif	    return;	}}Window CGetFocus(void){    return current_focus;}Window CGetICFocus(void){    return current_ic_focus;}void CFocusLast (void){    Window w;    if (!focus_sp)	return;    w = focus_stack[focus_sp - 1];    if (w == current_focus)	return;    if (w)	focus_window (w);}/*   Each main window must record its last focussed window. This is so   that when the window manager sets the focus to a main window. We   can look up what widget within that window last had the focus, and   move focus to that widget. */static Window *get_last_focussed_in_main (Window main){    static Window dummy;    CWidget *w;    w = CWidgetOfWindow (main);    if (w)	return &(w->last_child_focussed);    dummy = 0;    return &dummy;		/* instead of 'return 0;' to prevent segfaults */}/* {{{ Focus border creation and rendering *//* this is four windows that surround the focussed window */struct focus_win focus_border ={    0, 0, 0, 0, 0, 0, 0};Window get_focus_border_widget (void){    return focus_border.current;}/* draw a focus window around wodget w */void create_focus_border (CWidget * w, int border){    int x, y;    XSetWindowAttributes xswa;    xswa.colormap = CColormap;    xswa.bit_gravity = NorthWestGravity;    if (border > 2)	xswa.background_pixel = color_palette(17);	/* for drag and drop highlight borders */    else	xswa.background_pixel = COLOR_FLAT;    if (w->parentid == CRoot) {	xswa.override_redirect = 1;    } else {	xswa.override_redirect = 0;    }    focus_border.border = border;    x = w->x;    y = w->y;    if (w->parentid == CRoot) {	Window child;	XTranslateCoordinates(CDisplay, w->winid, CRoot, 0, 0, &x, &y, &child);    }    focus_border.top =	XCreateWindow (CDisplay, w->parentid,		      x - WIDGET_FOCUS_RING, y - WIDGET_FOCUS_RING,		     w->width + WIDGET_FOCUS_RING * 2, WIDGET_FOCUS_RING,		 0, CDepth, InputOutput, CVisual,	    CWOverrideRedirect | CWColormap | CWBackPixel | CWBitGravity,			    &xswa);    focus_border.bottom =	XCreateWindow (CDisplay, w->parentid,			     x - WIDGET_FOCUS_RING, y + w->height,		     w->width + WIDGET_FOCUS_RING * 2, WIDGET_FOCUS_RING,		 0, CDepth, InputOutput, CVisual,	    CWOverrideRedirect | CWColormap | CWBackPixel | CWBitGravity,			    &xswa);    focus_border.left =	XCreateWindow (CDisplay, w->parentid,			     x - WIDGET_FOCUS_RING, y,			     WIDGET_FOCUS_RING, w->height,		 0, CDepth, InputOutput, CVisual,	    CWOverrideRedirect | CWColormap | CWBackPixel | CWBitGravity,			    &xswa);    focus_border.right =	XCreateWindow (CDisplay, w->parentid,			     x + w->width, y,			     WIDGET_FOCUS_RING, w->height,		 0, CDepth, InputOutput, CVisual,	    CWOverrideRedirect | CWColormap | CWBackPixel | CWBitGravity,			    &xswa);    focus_border.current = w->winid;    focus_border.width = w->width;    focus_border.height = w->height;    XSelectInput (CDisplay, focus_border.top, ExposureMask);    XSelectInput (CDisplay, focus_border.bottom, ExposureMask);    XSelectInput (CDisplay, focus_border.left, ExposureMask);    XSelectInput (CDisplay, focus_border.right, ExposureMask);    XMapWindow (CDisplay, focus_border.top);    XMapWindow (CDisplay, focus_border.bottom);    XMapWindow (CDisplay, focus_border.left);    XMapWindow (CDisplay, focus_border.right);}void destroy_focus_border (void){    if (!focus_border.top)	return;    XDestroyWindow (CDisplay, focus_border.top);    XDestroyWindow (CDisplay, focus_border.bottom);    XDestroyWindow (CDisplay, focus_border.left);    XDestroyWindow (CDisplay, focus_border.right);    memset (&focus_border, 0, sizeof (focus_border));}int window_of_focus_border (Window win){    if (!focus_border.top)	return 0;    if (win == focus_border.top)	return 1;    if (win == focus_border.bottom)	return 1;    if (win == focus_border.left)	return 1;    if (win == focus_border.right)	return 1;    return 0;}void render_focus_border (Window win){    (*look->render_focus_border) (win);}static void set_ic_focus (CWidget * w){#ifdef USE_XIM    if (w->mainid) {	CIC = (CWidgetOfWindow (w->mainid))->input_context;	current_ic_focus = w->mainid;    } else {	CIC = w->input_context;	current_ic_focus = w->mainid;    }    if (CIC)	XSetICFocus (CIC);#endif}/* }}} Focus border creation and rendering *//* This is called when the app (and not the WM) wants to change focus. */static void focus_widget (CWidget * w){    CWidget *old;    if (current_focus == w->winid) {#ifdef FOCUS_DEBUG	printf ("current_focus == w->winid, returning\n");#endif	return;    }    destroy_focus_border ();    if ((w->options & WIDGET_TAKES_FOCUS_RING))	create_focus_border (w, 1);    old = CWidgetOfWindow (current_focus);    current_focus = w->winid;	/* notify library of new focus */    CSendMessage (old, FocusOut);	/* unfocus the current focus *//* focus on the widgets main window if it has changed */    if (old) {	if (old->mainid != w->mainid)	    goto set_main;    } else {      set_main:/* set that main windows 'last_child_focussed' */	XSetInputFocus (CDisplay, w->mainid, RevertToNone, CurrentTime);	set_ic_focus (w);    }    *(get_last_focussed_in_main (w->mainid)) = w->winid;#ifdef FOCUS_DEBUG    printf ("setting last_focus of %s = %s\n", (char *) CWidgetOfWindow (w->mainid), w->ident);#endif    add_to_focus_stack (w->winid);	/* record focus history *//* focus the new widget */    CSendMessage (w, FocusIn);}static void focus_main (Window main, int type){    CWidget *w;    if (type == FocusOut) {	w = CWidgetOfWindow (current_focus);#ifdef FOCUS_DEBUG	printf ("focus_main(Out): %s\n", w->ident);#endif	current_focus = -1;	/* inform the library that nothing is focussed */	CSendMessage (w, FocusOut);	destroy_focus_border ();    } else {			/* type == FocusIn *//* find the widget within this main that last had the focus: */	current_focus = *(get_last_focussed_in_main (main));	w = CWidgetOfWindow (current_focus);#ifdef FOCUS_DEBUG	printf ("focus_main(In): %s\n", w->ident);#endif	if (w) {	    add_to_focus_stack (w->winid);	/* record focus history */	    CSendMessage (w, FocusIn);	/* focus the new widget */	    if ((w->options & WIDGET_TAKES_FOCUS_RING))		create_focus_border (w, 2);	    set_ic_focus (w);	}    }}/*    This is called from CNextEvent when the WM sends   focus to a new different main window. */void process_external_focus (Window win, int type){    CWidget *w;#ifdef FOCUS_DEBUG    printf ("Entering process_external_focus()\n");#endif    w = CWidgetOfWindow (win);    if (!w) {#ifdef FOCUS_DEBUG	printf ("Leaving process_external_focus() - not our window\n");#endif	return;    }#ifdef FOCUS_DEBUG    printf ("widget = %s\n", w->ident);#endif    if (w->parentid == CRoot) {	/* should always be true since only 				   main windows have FocusChangeMask */	focus_main (w->winid, type);#ifdef FOCUS_DEBUG	printf ("Leaving process_external_focus() - main window\n");#endif	return;    } else {#ifdef FOCUS_DEBUG	printf ("Leaving process_external_focus() - not main window\n");#endif    }}void focus_window (Window win){    CWidget *w;    w = CWidgetOfWindow (win);    if (w)	CFocusNormal (w);}/* CFocus() is a macro for */void CFocusNormal (CWidget * w){    if (!w)	return;    if (!w->takes_focus)	return;    if (w->mapped & WINDOW_MAPPED) {	focus_widget (w);    } else {	w->mapped |= WINDOW_FOCUS_WHEN_MAPPED;    }}void CFocusDebug (CWidget *w, int line, char *file){/* NLS ? */    printf ("CFocus(%x): %s:%d (ident = %s)\n", (unsigned int) w->winid, file, line, w->ident);    CFocusNormal (w);}/* get next sibling of w that has takes_focus set (i.e. that takes user input of any sort) */CWidget *CNextFocus (CWidget * w){    int i, j;    i = j = find_next_child_of (w->parentid, w->winid);    for (;;) {	if (!i) {	    i = find_first_child_of (w->parentid);	    if (!i)		return 0;	}	if (CIndex (i)->takes_focus && !CIndex(i)->disabled)	    return CIndex (i);	w = CIndex (i);	i = find_next_child_of (w->parentid, w->winid);	if (i == j) /* done a round trip */	    return 0;    }}/* previous sibling of same */CWidget *CPreviousFocus (CWidget * w){    int i, j;    i = j = find_previous_child_of (w->parentid, w->winid);    for (;;) {	if (!i) {	    i = find_last_child_of (w->parentid);	    if (!i)		return 0;	}	if (CIndex (i)->takes_focus && !CIndex(i)->disabled)	    return CIndex (i);	w = CIndex (i);	i = find_previous_child_of (w->parentid, w->winid);	if (i == j) /* done a round trip */	    return 0;    }}/* first child of widget that takes focus (eg w is a window and    a button in the window is returned) */CWidget *CChildFocus (CWidget * w){    int j, i = find_first_child_of (w->winid);    if(!i)	return 0;    w = CIndex (i);    if(w->takes_focus)	return w;    j = i = find_next_child_of (w->parentid, w->winid);    for (;;) {	if (!i) {	    i = find_first_child_of (w->parentid);	    if (!i)		return 0;	}	if (CIndex (i)->takes_focus)	    return CIndex (i);	w = CIndex (i);	i = find_next_child_of (w->parentid, w->winid);	if (i == j) /* done a round trip */	    return 0;    }}/* search for two generations down for the first descendent that is a widget.   If it does not take focus, then its first child is focussed.   If it has no children, the next descendent is searched for. */CWidget *CFindFirstDescendent (Window win){    int i, j;    i = find_first_child_of (win);    if (i) {			/* is it a child ? */	if (CIndex (i)->takes_focus && !CIndex (i)->disabled) {	    return (CIndex (i));	} else {	    CWidget *w;	    w = CChildFocus (CIndex (i));	    if (w)		return w;	}    } else {			/* not a child */	Window root, parent, *children = 0;	unsigned int nchildren = 0;	if (!win)	    return 0;	XQueryTree (CDisplay, win, &root, &parent, &children, &nchildren);	if (!nchildren) {	    if (children)		XFree (children);	    return 0;	}	for (j = 0; j < nchildren; j++)	    if ((i = find_first_child_of (children[j]))) {	/* is it a grandchild ? */		if (CIndex (i)->takes_focus && !CIndex (i)->disabled) {		    XFree (children);		    return (CIndex (i));		} else {		    CWidget *w;		    w = CChildFocus (CIndex (i));		    if (w) {			XFree (children);			return w;		    }		}	    }	XFree (children);    }    return 0;			/* not a grandchild */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -