tImproved handling of keyboard focus in Win32 client - vaccinewars - be a docto… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 7cef0a26da1a6945e69f3cb16466782112d01378 | |
parent d84f46d131db94637615682f63fd7fa2b3a1ea62 | |
Author: Ben Webb <[email protected]> | |
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(-) | |
--- | |
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 wPar… | |
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 recur… | |
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 recur… | |
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 recur… | |
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 recu… | |
} | |
} | |
+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(… | |
+ GTK_WINDOW(window)->focus=widget; | |
+ if (widget->hWnd) { | |
+// if (!SetFocus(widget->hWnd)) g_print("SetFocus failed on widget %p\n",wi… | |
+ 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)->klas… | |
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,… | |
} | |
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) { | |
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)) | |