tImproved handling of keyboard focus in Win32 client - vaccinewars - be a doctor and try to vaccinate the world
(HTM) git clone git://src.adamsgaard.dk/vaccinewars
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 7cef0a26da1a6945e69f3cb16466782112d01378
(DIR) parent d84f46d131db94637615682f63fd7fa2b3a1ea62
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Fri, 15 Dec 2000 20:25:35 +0000
Improved handling of keyboard focus in Win32 client
Diffstat:
M src/gtk.c | 136 +++++++++++++++++++++++++++++--
M src/gtk.h | 5 +++++
2 files changed, 135 insertions(+), 6 deletions(-)
---
(DIR) diff --git a/src/gtk.c b/src/gtk.c
t@@ -163,6 +163,10 @@ static void gtk_clist_update_all_widths(GtkCList *clist);
static void gtk_clist_do_auto_resize(GtkCList *clist);
static void gtk_clist_set_column_width_full(GtkCList *clist,gint column,
gint width,gboolean ResizeHeader);
+static void gtk_widget_set_focus(GtkWidget *widget);
+static void gtk_widget_lose_focus(GtkWidget *widget);
+static void gtk_window_update_focus(GtkWindow *window);
+static void gtk_window_set_focus(GtkWindow *window);
typedef struct _GdkInput GdkInput;
t@@ -627,6 +631,24 @@ LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,UINT wParam,LONG lParam) {
alloc.height=rect.bottom-rect.top;
gtk_widget_set_size(window,&alloc);
break;
+ case WM_ACTIVATE:
+ case WM_ACTIVATEAPP:
+ widget=GTK_WIDGET(GetWindowLong(hwnd,GWL_USERDATA));
+ if (widget) klass=GTK_OBJECT(widget)->klass; else klass=NULL;
+ if (klass==&GtkWindowClass) {
+ if ((msg==WM_ACTIVATE && LOWORD(wParam)!=WA_INACTIVE)||
+ (msg==WM_ACTIVATEAPP && wParam)) {
+ if (GTK_WINDOW(widget)->focus) {
+ gtk_widget_set_focus(GTK_WINDOW(widget)->focus);
+ }
+ if (!GTK_WINDOW(widget)->focus) {
+ gtk_window_set_focus(GTK_WINDOW(widget));
+ }
+ } else if (msg==WM_ACTIVATE && LOWORD(wParam)==WA_INACTIVE) {
+ gtk_window_update_focus(GTK_WINDOW(widget));
+ }
+ }
+ break;
case WM_COMMAND:
widget=GTK_WIDGET(GetWindowLong((HWND)lParam,GWL_USERDATA));
if (widget) klass=GTK_OBJECT(widget)->klass; else klass=NULL;
t@@ -761,6 +783,7 @@ void gtk_widget_show_full(GtkWidget *widget,gboolean recurse) {
if (GTK_WIDGET_VISIBLE(widget)) return;
GTK_WIDGET_SET_FLAGS(widget,GTK_VISIBLE);
+
if (recurse) gtk_widget_show_all_full(widget,TRUE);
else gtk_signal_emit(GTK_OBJECT(widget),"show");
t@@ -777,6 +800,9 @@ void gtk_widget_show_full(GtkWidget *widget,gboolean recurse) {
gtk_widget_update(widget,TRUE);
if (!recurse) ShowWindow(widget->hWnd,SW_SHOWNORMAL);
}
+
+// g_print("widget show - set focus\n");
+ gtk_widget_set_focus(widget);
}
void gtk_widget_hide(GtkWidget *widget) {
t@@ -790,6 +816,8 @@ void gtk_widget_hide_full(GtkWidget *widget,gboolean recurse) {
if (!GTK_WIDGET_VISIBLE(widget)) return;
+ gtk_widget_lose_focus(widget);
+
if (recurse) gtk_widget_hide_all_full(widget,TRUE);
else {
gtk_signal_emit(GTK_OBJECT(widget),"hide");
t@@ -815,6 +843,70 @@ void gtk_widget_hide_full(GtkWidget *widget,gboolean recurse) {
}
}
+void gtk_widget_set_focus(GtkWidget *widget) {
+ GtkWidget *window;
+ if (!widget || !GTK_WIDGET_CAN_FOCUS(widget) ||
+ !GTK_WIDGET_SENSITIVE(widget) || !GTK_WIDGET_VISIBLE(widget)) return;
+ window=gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW);
+ gtk_window_update_focus(GTK_WINDOW(window));
+ if (!window || GTK_WINDOW(window)->focus) return;
+
+// g_print("Window %p focus set to widget %p (%s)\n",window,widget,GTK_OBJECT(widget)->klass->Name);
+ GTK_WINDOW(window)->focus=widget;
+ if (widget->hWnd) {
+// if (!SetFocus(widget->hWnd)) g_print("SetFocus failed on widget %p\n",widget);
+ SetFocus(widget->hWnd);
+ }
+// else g_print("Cannot call SetFocus - no hWnd\n");
+}
+
+static BOOL CALLBACK SetFocusEnum(HWND hWnd,LPARAM data) {
+ GtkWidget *widget;
+ GtkWindow *window=GTK_WINDOW(data);
+ widget=GTK_WIDGET(GetWindowLong(hWnd,GWL_USERDATA));
+ if (!widget || !GTK_WIDGET_CAN_FOCUS(widget) ||
+ !GTK_WIDGET_SENSITIVE(widget) || !GTK_WIDGET_VISIBLE(widget) ||
+ window->focus==widget) {
+ return TRUE;
+ } else {
+//g_print("gtk_window_set_focus: focus set to widget %p\n",widget);
+ window->focus=widget;
+ SetFocus(widget->hWnd);
+ return FALSE;
+ }
+}
+
+void gtk_window_set_focus(GtkWindow *window) {
+ if (!window||!GTK_WIDGET(window)->hWnd) return;
+ EnumChildWindows(GTK_WIDGET(window)->hWnd,SetFocusEnum,(LPARAM)window);
+}
+
+void gtk_widget_lose_focus(GtkWidget *widget) {
+ GtkWidget *window;
+ if (!widget || !GTK_WIDGET_CAN_FOCUS(widget) ||
+ !GTK_WIDGET_SENSITIVE(widget) || !GTK_WIDGET_VISIBLE(widget)) return;
+ window=gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW);
+ gtk_window_update_focus(GTK_WINDOW(window));
+ if (GTK_WINDOW(window)->focus==widget) {
+ gtk_window_set_focus(GTK_WINDOW(window));
+ }
+}
+
+void gtk_window_update_focus(GtkWindow *window) {
+ GtkWidget *widget;
+ HWND FocusWnd;
+ if (GTK_WIDGET(window)->hWnd != GetActiveWindow()) return;
+ FocusWnd=GetFocus();
+ window->focus=NULL;
+ if (FocusWnd) {
+ widget=GTK_WIDGET(GetWindowLong(FocusWnd,GWL_USERDATA));
+ if (widget && GTK_WIDGET(window)->hWnd &&
+ GetParent(FocusWnd)==GTK_WIDGET(window)->hWnd) {
+ window->focus=widget;
+ } /*else g_print("Widget %p is not child of window %p\n",widget,window);*/
+ }// else g_print("GetFocus returned NULL\n");
+}
+
void gtk_widget_realize(GtkWidget *widget) {
GtkRequisition req;
/* g_print("Realizing widget %p of class %s\n",widget,GTK_OBJECT(widget)->klass->Name);*/
t@@ -822,6 +914,7 @@ void gtk_widget_realize(GtkWidget *widget) {
if (widget->hWnd) SetWindowLong(widget->hWnd,GWL_USERDATA,(LONG)widget);
GTK_WIDGET_SET_FLAGS(widget,GTK_REALIZED);
gtk_widget_set_sensitive(widget,GTK_WIDGET_SENSITIVE(widget));
+
gtk_widget_size_request(widget,&req);
}
t@@ -831,6 +924,7 @@ void gtk_widget_create(GtkWidget *widget) {
void gtk_widget_destroy(GtkWidget *widget) {
if (!widget) return;
+ gtk_widget_lose_focus(widget);
// g_print("gtk_widget_destroy on widget %p\n",widget);
gtk_signal_emit(GTK_OBJECT(widget),"destroy");
// g_print("Freeing widget\n");
t@@ -839,10 +933,17 @@ void gtk_widget_destroy(GtkWidget *widget) {
}
void gtk_widget_set_sensitive(GtkWidget *widget,gboolean sensitive) {
- if (widget->hWnd) EnableWindow(widget->hWnd,sensitive);
+ if (sensitive) {
+ GTK_WIDGET_SET_FLAGS(widget,GTK_SENSITIVE);
+ if (widget->hWnd) EnableWindow(widget->hWnd,sensitive);
+ gtk_widget_set_focus(widget);
+ } else {
+ gtk_widget_lose_focus(widget);
+ GTK_WIDGET_UNSET_FLAGS(widget,GTK_SENSITIVE);
+ if (widget->hWnd) EnableWindow(widget->hWnd,sensitive);
+ }
+
gtk_signal_emit(GTK_OBJECT(widget),sensitive ? "enable" : "disable");
- if (sensitive) GTK_WIDGET_SET_FLAGS(widget,GTK_SENSITIVE);
- else GTK_WIDGET_UNSET_FLAGS(widget,GTK_SENSITIVE);
if (sensitive && widget->hWnd && GTK_OBJECT(widget)->klass==&GtkWindowClass)
SetActiveWindow(widget->hWnd);
}
t@@ -1561,7 +1662,7 @@ void gtk_window_realize(GtkWidget *widget) {
widget->hWnd = CreateWindow("mainwin",win->title,
win->type == GTK_WINDOW_TOPLEVEL ?
WS_OVERLAPPEDWINDOW|CS_HREDRAW|CS_VREDRAW|WS_SIZEBOX :
- WS_CAPTION|WS_SYSMENU|CS_HREDRAW|CS_VREDRAW,
+ WS_CAPTION|WS_SYSMENU|CS_HREDRAW|CS_VREDRAW|WS_SIZEBOX,
CW_USEDEFAULT,0,
widget->allocation.width,widget->allocation.height,
Parent,NULL,hInst,NULL);
t@@ -1570,6 +1671,7 @@ void gtk_window_realize(GtkWidget *widget) {
gtk_set_default_font(widget->hWnd);
/* g_print("Window window %p created\n",widget->hWnd);*/
gtk_container_realize(widget);
+// if (win->focus && win->focus->hWnd) SetFocus(win->focus->hWnd);
}
void gtk_container_realize(GtkWidget *widget) {
t@@ -1602,6 +1704,7 @@ HWND gtk_get_parent_hwnd(GtkWidget *widget) {
void gtk_button_realize(GtkWidget *widget) {
GtkButton *but=GTK_BUTTON(widget);
HWND Parent;
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
Parent=gtk_get_parent_hwnd(widget);
widget->hWnd = CreateWindow("BUTTON",but->text,
WS_CHILD|WS_TABSTOP|BS_PUSHBUTTON,
t@@ -1614,6 +1717,7 @@ void gtk_button_realize(GtkWidget *widget) {
void gtk_entry_realize(GtkWidget *widget) {
HWND Parent;
Parent=gtk_get_parent_hwnd(widget);
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
widget->hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","",
WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL,
widget->allocation.x,widget->allocation.y,
t@@ -1629,6 +1733,7 @@ void gtk_entry_realize(GtkWidget *widget) {
void gtk_text_realize(GtkWidget *widget) {
HWND Parent;
Parent=gtk_get_parent_hwnd(widget);
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
widget->hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","",
WS_CHILD|WS_TABSTOP|
ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL|
t@@ -1660,6 +1765,7 @@ void gtk_check_button_realize(GtkWidget *widget) {
HWND Parent;
gboolean toggled;
Parent=gtk_get_parent_hwnd(widget);
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
widget->hWnd = CreateWindow("BUTTON",but->text,
WS_CHILD|WS_TABSTOP|BS_CHECKBOX,
widget->allocation.x,widget->allocation.y,
t@@ -1680,6 +1786,7 @@ void gtk_radio_button_realize(GtkWidget *widget) {
HWND Parent;
gboolean toggled;
Parent=gtk_get_parent_hwnd(widget);
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
widget->hWnd = CreateWindow("BUTTON",but->text,
WS_CHILD|WS_TABSTOP|BS_RADIOBUTTON,
widget->allocation.x,widget->allocation.y,
t@@ -1744,6 +1851,7 @@ void gtk_clist_realize(GtkWidget *widget) {
gtk_container_realize(widget);
Parent=gtk_get_parent_hwnd(widget);
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
rcParent.left = rcParent.top = 0;
rcParent.right = rcParent.bottom = 800;
header=CreateWindowEx(0,WC_HEADER,NULL,
t@@ -2962,8 +3070,9 @@ void gtk_notebook_realize(GtkWidget *widget) {
TC_ITEM tie;
Parent=gtk_get_parent_hwnd(widget);
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
widget->hWnd = CreateWindow(WC_TABCONTROL,"",
- WS_CHILD,0,0,0,0,
+ WS_CHILD|WS_TABSTOP,0,0,0,0,
Parent,NULL,hInst,NULL);
if (widget->hWnd==NULL) g_print("Error creating window!\n");
gtk_set_default_font(widget->hWnd);
t@@ -3174,7 +3283,8 @@ void gtk_spin_button_realize(GtkWidget *widget) {
gtk_entry_realize(widget);
Parent=gtk_get_parent_hwnd(widget->parent);
- spin->updown=CreateUpDownControl(WS_CHILD|WS_BORDER|
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
+ spin->updown=CreateUpDownControl(WS_CHILD|WS_BORDER|WS_TABSTOP|
UDS_SETBUDDYINT|UDS_NOTHOUSANDS|UDS_ARROWKEYS,
0,0,0,0,Parent,0,hInst,widget->hWnd,20,10,15);
gtk_set_default_font(spin->updown);
t@@ -3270,6 +3380,9 @@ void gtk_widget_grab_default(GtkWidget *widget) {
}
void gtk_widget_grab_focus(GtkWidget *widget) {
+ if (widget->hWnd && GTK_WIDGET_CAN_FOCUS(widget)) {
+ SetFocus(widget->hWnd);
+ }
}
void gtk_window_set_modal(GtkWindow *window,gboolean modal) {
t@@ -3524,6 +3637,7 @@ void gtk_option_menu_realize(GtkWidget *widget) {
GtkOptionMenu *option_menu=GTK_OPTION_MENU(widget);
Parent=gtk_get_parent_hwnd(widget);
+ GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
widget->hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,"COMBOBOX","",
WS_CHILD|WS_TABSTOP|WS_VSCROLL|
CBS_HASSTRINGS|CBS_DROPDOWNLIST,
t@@ -3612,6 +3726,16 @@ void gtk_widget_set_usize(GtkWidget *widget,gint width,gint height) {
}
void gtk_clist_select_row(GtkCList *clist,gint row,gint column) {
+ HWND hWnd;
+ hWnd=GTK_WIDGET(clist)->hWnd;
+ if (hWnd) {
+ if (clist->mode==GTK_SELECTION_SINGLE) {
+ SendMessage(hWnd,LB_SETCURSEL,(WPARAM)row,0);
+ } else {
+ SendMessage(hWnd,LB_SETSEL,(WPARAM)TRUE,(LPARAM)row);
+ }
+ gtk_clist_update_selection(GTK_WIDGET(clist));
+ }
}
GtkVisibility gtk_clist_row_is_visible(GtkCList *clist,gint row) {
(DIR) diff --git a/src/gtk.h b/src/gtk.h
t@@ -48,6 +48,8 @@ typedef enum {
GTK_REALIZED = 1 << 6,
GTK_VISIBLE = 1 << 8,
GTK_SENSITIVE = 1 << 10,
+ GTK_CAN_FOCUS = 1 << 11,
+ GTK_HAS_FOCUS = 1 << 12,
GTK_CAN_DEFAULT = 1 << 13
} GtkWidgetFlags;
t@@ -366,6 +368,7 @@ struct _GtkWindow {
gint default_width,default_height;
GtkMenuBar *menu_bar;
GtkAccelGroup *accel_group;
+ GtkWidget *focus;
HACCEL hAccel;
guint modal : 1;
};
t@@ -430,6 +433,8 @@ struct _GtkTableRowCol {
#define GTK_WIDGET_REALIZED(wid) ((GTK_WIDGET_FLAGS(wid)>K_REALIZED) != 0)
#define GTK_WIDGET_VISIBLE(wid) ((GTK_WIDGET_FLAGS(wid)>K_VISIBLE) != 0)
#define GTK_WIDGET_SENSITIVE(wid) ((GTK_WIDGET_FLAGS(wid)>K_SENSITIVE) != 0)
+#define GTK_WIDGET_CAN_FOCUS(wid) ((GTK_WIDGET_FLAGS(wid)>K_CAN_FOCUS) != 0)
+#define GTK_WIDGET_HAS_FOCUS(wid) ((GTK_WIDGET_FLAGS(wid)>K_HAS_FOCUS) != 0)
#define GTK_WIDGET_SET_FLAGS(wid,flag) (GTK_WIDGET_FLAGS(wid) |= (flag))
#define GTK_WIDGET_UNSET_FLAGS(wid,flag) (GTK_WIDGET_FLAGS(wid) &= ~(flag))