# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1010969288 0 # Node ID a6801a2260af35c9b3a0cb6f9c1a799a57ad2bea # Parent 2be5174bdb5d86d4d470c48bf1d3fe9a675bebfb Synched up with the latest dynamic windows, has new slider support and transparency, focus, and other bug fixes on various platforms. diff -r 2be5174bdb5d -r a6801a2260af dw.def --- a/dw.def Sat Dec 08 04:47:43 2001 +0000 +++ b/dw.def Mon Jan 14 00:48:08 2002 +0000 @@ -208,6 +208,11 @@ dw_tree_collapse @376 dw_tree_item_select @377 dw_tree_set_data @378 + dw_tree_insert_after @379 dw_font_text_extents @380 + dw_slider_new @390 + dw_slider_query_pos @391 + dw_slider_set_pos @392 + diff -r 2be5174bdb5d -r a6801a2260af dw.h --- a/dw.h Sat Dec 08 04:47:43 2001 +0000 +++ b/dw.h Mon Jan 14 00:48:08 2002 +0000 @@ -614,6 +614,7 @@ HWND dw_spinbutton_new(char *text, unsigned long id); HWND dw_radiobutton_new(char *text, ULONG id); HWND dw_percent_new(unsigned long id); +HWND dw_slider_new(int vertical, int increments, ULONG id); HWND dw_checkbox_new(char *text, unsigned long id); HWND dw_listbox_new(unsigned long id, int multi); void dw_listbox_append(HWND handle, char *text); @@ -628,6 +629,8 @@ int dw_listbox_selected_multi(HWND handle, int where); unsigned int dw_percent_query_range(HWND handle); void dw_percent_set_pos(HWND handle, unsigned int position); +unsigned int dw_slider_query_pos(HWND handle); +void dw_slider_set_pos(HWND handle, unsigned int position); void dw_window_set_pos(HWND handle, unsigned long x, unsigned long y); void dw_window_set_usize(HWND handle, unsigned long width, unsigned long height); void dw_window_set_pos_size(HWND handle, unsigned long x, unsigned long y, unsigned long width, unsigned long height); diff -r 2be5174bdb5d -r a6801a2260af dww.def --- a/dww.def Sat Dec 08 04:47:43 2001 +0000 +++ b/dww.def Mon Jan 14 00:48:08 2002 +0000 @@ -205,6 +205,11 @@ dw_tree_collapse @376 dw_tree_item_select @377 dw_tree_set_data @378 + dw_tree_insert_after @379 dw_font_text_extents @380 + dw_slider_new @390 + dw_slider_query_pos @391 + dw_slider_set_pos @392 + diff -r 2be5174bdb5d -r a6801a2260af gtk/dw.c --- a/gtk/dw.c Sat Dec 08 04:47:43 2001 +0000 +++ b/gtk/dw.c Mon Jan 14 00:48:08 2002 +0000 @@ -3,7 +3,7 @@ * A GTK like implementation of the PM GUI * GTK forwarder module for portabilty. * - * (C) 2000,2001 Brian Smith + * (C) 2000-2002 Brian Smith * */ #include "dw.h" @@ -91,6 +91,8 @@ void _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data); void _tree_select_event(GtkTree *tree, GtkWidget *child, gpointer data); void _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data); +void _value_changed_event(GtkAdjustment *adjustment, gpointer user_data); + void msleep(long period); @@ -109,7 +111,7 @@ } SignalHandler; -#define SIGNALMAX 15 +#define SIGNALMAX 16 /* A list of signal forwarders, to account for paramater differences. */ SignalList SignalTranslate[SIGNALMAX] = { @@ -127,7 +129,8 @@ { _tree_context_event, "tree-context" }, { _item_select_event, "item-select" }, { _tree_select_event, "tree-select" }, - { _set_focus_event, "set-focus" } + { _set_focus_event, "set-focus" }, + { _value_changed_event, "value_changed" } }; /* Alignment flags */ @@ -464,6 +467,39 @@ } } +int _round_value(gfloat val) +{ + int newval = (int)val; + + if(val >= 0.5 + (gfloat)newval) + newval++; + + return newval; +} + +void _value_changed_event(GtkAdjustment *adjustment, gpointer data) +{ + GtkWidget *slider = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(adjustment), "slider"); + SignalHandler *work = (SignalHandler *)data; + + if(slider && work) + { + int (*valuechangedfunc)(HWND, int, void *) = work->func; + int max = _round_value(adjustment->upper) - 1; + int val = _round_value(adjustment->value); + static int lastval = -1; + static GtkWidget *lastwidget = 0; + + if(lastval != val || lastwidget != slider) + { + if(GTK_IS_VSCALE(slider)) + valuechangedfunc(work->window, max - val, work->data); + else + valuechangedfunc(work->window, val, work->data); + } + } +} + gint _default_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data) { GtkWidget *next = (GtkWidget *)data; @@ -633,17 +669,21 @@ } /* - * Runs a message loop for Dynamic Windows, for a period of seconds. + * Runs a message loop for Dynamic Windows, for a period of milliseconds. * Parameters: - * seconds: Number of seconds to run the loop for. - */ -void dw_main_sleep(int seconds) -{ - time_t start = time(NULL); + * milliseconds: Number of milliseconds to run the loop for. + */ +void dw_main_sleep(int milliseconds) +{ + struct timeval tv, start; + + gettimeofday(&start, NULL); if(_dw_thread == (pthread_t)-1 || _dw_thread == pthread_self()) { - while(time(NULL) - start <= seconds) + gettimeofday(&tv, NULL); + + while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds) { gdk_threads_enter(); if(gtk_events_pending()) @@ -651,10 +691,11 @@ else msleep(1); gdk_threads_leave(); + gettimeofday(&tv, NULL); } } else - msleep(seconds * 1000); + msleep(milliseconds); } /* @@ -2040,6 +2081,35 @@ } /* + * Create a new slider window (widget) to be packed. + * Parameters: + * vertical: TRUE or FALSE if slider is vertical. + * increments: Number of increments available. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_slider_new(int vertical, int increments, ULONG id) +{ + GtkWidget *tmp; + GtkAdjustment *adjustment; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + adjustment = (GtkAdjustment *)gtk_adjustment_new(0, 0, (gfloat)(increments + 1), 1, 1, 1); + if(vertical) + tmp = gtk_vscale_new(adjustment); + else + tmp = gtk_hscale_new(adjustment); + gtk_widget_show(tmp); + gtk_scale_set_draw_value(GTK_SCALE(tmp), 0); + gtk_scale_set_digits(GTK_SCALE(tmp), 0); + gtk_object_set_data(GTK_OBJECT(tmp), "adjustment", (gpointer)adjustment); + gtk_object_set_data(GTK_OBJECT(adjustment), "slider", (gpointer)tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* * Create a new percent bar window (widget) to be packed. * Parameters: * id: An ID to be used with WinWindowFromID() or 0L. @@ -2628,7 +2698,7 @@ /* * Returns the range of the percent bar. * Parameters: - * handle: Handle to the slider to be queried. + * handle: Handle to the percent bar to be queried. */ unsigned int dw_percent_query_range(HWND handle) { @@ -2638,8 +2708,8 @@ /* * Sets the percent bar position. * Parameters: - * handle: Handle to the slider to be set. - * position: Position of the slider withing the range. + * handle: Handle to the percent bar to be set. + * position: Position of the percent bar withing the range. */ void dw_percent_set_pos(HWND handle, unsigned int position) { @@ -2651,6 +2721,63 @@ } /* + * Returns the position of the slider. + * Parameters: + * handle: Handle to the slider to be queried. + */ +unsigned int dw_slider_query_pos(HWND handle) +{ + int val = 0, _locked_by_me = FALSE; + GtkAdjustment *adjustment; + + if(!handle) + return 0; + + DW_MUTEX_LOCK; + adjustment = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(handle), "adjustment"); + if(adjustment) + { + int max = _round_value(adjustment->upper) - 1; + int thisval = _round_value(adjustment->value); + + if(GTK_IS_VSCALE(handle)) + val = max - thisval; + else + val = thisval; + } + DW_MUTEX_UNLOCK; + return val; +} + +/* + * Sets the slider position. + * Parameters: + * handle: Handle to the slider to be set. + * position: Position of the slider withing the range. + */ +void dw_slider_set_pos(HWND handle, unsigned int position) +{ + int _locked_by_me = FALSE; + GtkAdjustment *adjustment; + + if(!handle) + return; + + DW_MUTEX_LOCK; + adjustment = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(handle), "adjustment"); + if(adjustment) + { + int max = _round_value(adjustment->upper) - 1; + + if(GTK_IS_VSCALE(handle)) + gtk_adjustment_set_value(adjustment, (gfloat)(max - position)); + else + gtk_adjustment_set_value(adjustment, (gfloat)position); + } + DW_MUTEX_UNLOCK; +} + +/* * Sets the spinbutton value. * Parameters: * handle: Handle to the spinbutton to be set. @@ -5606,6 +5733,10 @@ } thisname = "select-child"; } + else if(GTK_IS_VSCALE(thiswindow) || GTK_IS_HSCALE(thiswindow)) + { + thiswindow = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(thiswindow), "adjustment"); + } if(!thisfunc || !thiswindow) { diff -r 2be5174bdb5d -r a6801a2260af os2/dw.c --- a/os2/dw.c Sat Dec 08 04:47:43 2001 +0000 +++ b/os2/dw.c Mon Jan 14 00:48:08 2002 +0000 @@ -2,7 +2,7 @@ * Dynamic Windows: * A GTK like implementation of the PM GUI * - * (C) 2000,2001 Brian Smith + * (C) 2000-2002 Brian Smith * (C) 2000 Achim Hasenmueller * (C) 2000 Peter Nielsen * (C) 1998 Sergey I. Yevtushenko (some code borrowed from cell toolkit) @@ -93,7 +93,7 @@ } SignalList; /* List of signals and their equivilent OS/2 message */ -#define SIGNALMAX 14 +#define SIGNALMAX 15 SignalList SignalTranslate[SIGNALMAX] = { { WM_SIZE, "configure_event" }, @@ -109,7 +109,8 @@ { LN_SELECT, "item-select" }, { CN_EMPHASIS, "tree-select" }, { WM_SETFOCUS, "set-focus" }, - { WM_USER+1, "lose-focus" } + { WM_USER+1, "lose-focus" }, + { SLN_SLIDERTRACK, "value_changed" } }; /* This function adds a signal handler callback into the linked list. @@ -186,8 +187,6 @@ if(strncmp(tmpbuf, "#3", 3)==0 && dw) /* Button */ WinSetOwner(child, dw); - if(strncmp(tmpbuf, "#38", 4)==0 && dw) /* Slider */ - WinSetOwner(child, 0); else if(strncmp(tmpbuf, "dynamicwindows", 14) == 0) dw = child; @@ -262,9 +261,10 @@ strncmp(tmpbuf, "#3", 3)==0 || /* Button */ strncmp(tmpbuf, "#6", 3)==0 || /* Entryfield */ strncmp(tmpbuf, "#7", 3)==0 || /* List box */ - strncmp(tmpbuf, "#10", 3)==0 || /* MLE */ - strncmp(tmpbuf, "#32", 3)==0 || /* Spinbutton */ - strncmp(tmpbuf, "#37", 3)== 0) /* Container */ + strncmp(tmpbuf, "#10", 4)==0 || /* MLE */ + strncmp(tmpbuf, "#32", 4)==0 || /* Spinbutton */ + strncmp(tmpbuf, "#37", 4)==0 || /* Container */ + strncmp(tmpbuf, "#38", 4)== 0) /* Slider */ return 1; return 0; } @@ -350,7 +350,7 @@ char tmpbuf[100] = ""; WinQueryClassName(box->items[z].hwnd, 99, tmpbuf); - if(strncmp(tmpbuf, "#40", 3)==0) /* Notebook */ + if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */ { Box *notebox; HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND, @@ -420,7 +420,7 @@ char tmpbuf[100] = ""; WinQueryClassName(box->items[z].hwnd, 99, tmpbuf); - if(strncmp(tmpbuf, "#40", 3)==0) /* Notebook */ + if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */ { Box *notebox; HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND, @@ -522,7 +522,7 @@ char tmpbuf[100] = ""; WinQueryClassName(box->items[z].hwnd, 99, tmpbuf); - if(strncmp(tmpbuf, "#40", 3)==0) /* Notebook */ + if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */ { Box *notebox; HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND, @@ -592,7 +592,7 @@ char tmpbuf[100] = ""; WinQueryClassName(box->items[z].hwnd, 99, tmpbuf); - if(strncmp(tmpbuf, "#40", 3)==0) /* Notebook */ + if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */ { Box *notebox; HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND, @@ -699,6 +699,22 @@ WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, swp.cx, swp.cy, SWP_SIZE); } +/* Focus toplevel window */ +void _toplevel_focus(HWND handle) +{ + HWND box, lastbox = WinQueryWindow(handle, QW_PARENT); + + /* Find the toplevel window */ + while((box = WinQueryWindow(lastbox, QW_PARENT)) > 0x80000001) + { + lastbox = box; + } + + box = WinWindowFromID(lastbox, FID_CLIENT); + if(box) + WinSetActiveWindow(HWND_DESKTOP, lastbox); +} + /* This function will recursively search a box and add up the total height of it */ void _count_size(HWND box, int type, int *xsize, int *xorigsize) { @@ -1238,27 +1254,37 @@ MRESULT EXPENTRY _sizeproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) { PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER); - - switch(msg) + Box *thisbox = NULL; + HWND box; + + box = WinWindowFromID(hWnd, FID_CLIENT); + if(box) + thisbox = WinQueryWindowPtr(box, QWP_USER); + + if(thisbox && !thisbox->titlebar) { - case WM_QUERYTRACKINFO: + switch(msg) { - if(blah && *blah) + case WM_QUERYTRACKINFO: { - PTRACKINFO ptInfo; - int res; - PFNWP myfunc = *blah; - res = (int)myfunc(hWnd, msg, mp1, mp2); - - ptInfo = (PTRACKINFO)(mp2); - - ptInfo->ptlMinTrackSize.y = 8; - ptInfo->ptlMinTrackSize.x = 8; - - return (MRESULT)res; + if(blah && *blah) + { + PTRACKINFO ptInfo; + int res; + PFNWP myfunc = *blah; + res = (int)myfunc(hWnd, msg, mp1, mp2); + + ptInfo = (PTRACKINFO)(mp2); + + ptInfo->ptlMinTrackSize.y = 8; + ptInfo->ptlMinTrackSize.x = 8; + + return (MRESULT)res; + } } } } + if(blah && *blah) { PFNWP myfunc = *blah; @@ -1362,17 +1388,6 @@ return WinDefWindowProc(hWnd, msg, mp1, mp2); } -/* This procedure handles drawing of a percent bar */ -MRESULT EXPENTRY _percentproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER); - - if(blah) - return blah->oldproc(hWnd, msg, mp1, mp2); - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - void _click_default(HWND handle) { char tmpbuf[100]; @@ -1416,6 +1431,7 @@ switch(msg) { case WM_SETFOCUS: + _toplevel_focus(hWnd); _run_event(hWnd, msg, mp1, mp2); break; } @@ -1447,11 +1463,22 @@ WinQueryClassName(hWnd, 99, tmpbuf); - if(strncmp(tmpbuf, "#32", 3)==0) + if(strncmp(tmpbuf, "#32", 4)==0) _run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE); } break; + case WM_CONTROL: + { + char tmpbuf[100]; + + WinQueryClassName(hWnd, 99, tmpbuf); + + if(strncmp(tmpbuf, "#38", 4)==0) + _run_event(hWnd, msg, mp1, mp2); + } + break; case WM_SETFOCUS: + _toplevel_focus(hWnd); _run_event(hWnd, msg, mp1, mp2); break; case WM_CHAR: @@ -1506,6 +1533,7 @@ _run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE); break; case WM_SETFOCUS: + _toplevel_focus(hWnd); _run_event(hWnd, msg, mp1, mp2); break; case WM_PAINT: @@ -1760,7 +1788,7 @@ } break; case WM_CONTROL: - if(tmp->message == SHORT2FROMMP(mp1)) + if(tmp->message == SHORT2FROMMP(mp1) || (tmp->message == SLN_SLIDERTRACK && SHORT2FROMMP(mp1) == SLN_CHANGE)) { switch(SHORT2FROMMP(mp1)) { @@ -1866,44 +1894,87 @@ break; case LN_SELECT: { - int (*listboxselectfunc)(HWND, int, void *) = (int (*)(HWND, int, void *))tmp->signalfunction; - int id = SHORT1FROMMP(mp1); - HWND conthwnd = dw_window_from_id(hWnd, id); - static int _recursing = 0; - - if(_recursing == 0 && (tmp->window == conthwnd || (!id && tmp->window == (HWND)mp2))) + char classbuf[100]; + + WinQueryClassName(tmp->window, 99, classbuf); + + if(strncmp(classbuf, "#38", 4) == 0) { - char buf1[500], classbuf[100]; - unsigned int index = dw_listbox_selected(tmp->window); - - dw_listbox_query_text(tmp->window, index, buf1, 500); - - WinQueryClassName(tmp->window, 99, classbuf); - - _recursing = 1; - - if(id && strncmp(classbuf, "#2", 3)==0) + int (*valuechangedfunc)(HWND, int, void *) = (int (*)(HWND, int, void *))tmp->signalfunction; + + if(tmp->window == hWnd || WinQueryWindow(tmp->window, QW_PARENT) == hWnd) + { + static int lastvalue = -1; + static HWND lasthwnd = NULLHANDLE; + int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); + if(lastvalue != ulValue || lasthwnd != tmp->window) + { + result = valuechangedfunc(tmp->window, ulValue, tmp->data); + lastvalue = ulValue; + lasthwnd = tmp->window; + } + tmp = NULL; + } + } + else + { + int (*listboxselectfunc)(HWND, int, void *) = (int (*)(HWND, int, void *))tmp->signalfunction; + int id = SHORT1FROMMP(mp1); + HWND conthwnd = dw_window_from_id(hWnd, id); + static int _recursing = 0; + + if(_recursing == 0 && (tmp->window == conthwnd || (!id && tmp->window == (HWND)mp2))) { - char *buf2; - - buf2 = dw_window_get_text(tmp->window); - - /* This is to make sure the listboxselect function doesn't - * get called if the user is modifying the entry text. - */ - if(buf2 && *buf2 && *buf1 && strncmp(buf1, buf2, 500) == 0) + char buf1[500]; + unsigned int index = dw_listbox_selected(tmp->window); + + dw_listbox_query_text(tmp->window, index, buf1, 500); + + _recursing = 1; + + if(id && strncmp(classbuf, "#2", 3)==0) + { + char *buf2; + + buf2 = dw_window_get_text(tmp->window); + + /* This is to make sure the listboxselect function doesn't + * get called if the user is modifying the entry text. + */ + if(buf2 && *buf2 && *buf1 && strncmp(buf1, buf2, 500) == 0) + result = listboxselectfunc(tmp->window, index, tmp->data); + + if(buf2) + free(buf2); + } + else result = listboxselectfunc(tmp->window, index, tmp->data); - if(buf2) - free(buf2); + _recursing = 0; + tmp = NULL; } - else - result = listboxselectfunc(tmp->window, index, tmp->data); - - _recursing = 0; + } + } + break; + case SLN_SLIDERTRACK: + { + int (*valuechangedfunc)(HWND, int, void *) = (int (*)(HWND, int, void *))tmp->signalfunction; + + if(tmp->window == hWnd || WinQueryWindow(tmp->window, QW_PARENT) == hWnd) + { + static int lastvalue = -1; + static HWND lasthwnd = NULLHANDLE; + int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); + if(lastvalue != ulValue || lasthwnd != tmp->window) + { + result = valuechangedfunc(tmp->window, ulValue, tmp->data); + lastvalue = ulValue; + lasthwnd = tmp->window; + } tmp = NULL; } } + break; } } @@ -1920,6 +1991,40 @@ } #endif +int _warp4_focus_fix(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + /* This is a hack to stop an infinite loop in the + * Warp 4 default window procedure. It seems that + * under very rare circumstances, the same WM_FOCUSCHANGE + * message will bounce between an entryfield and + * the frame it sits on, this will stop duplicate + * messages and thus prevent the infinite loop. + */ + if(msg == WM_FOCUSCHANGE && SHORT1FROMMP(mp2)) + { + static HWND lastfocus = 0; + static time_t lasttime = 0; + static int count = 0; + time_t currtime = time(NULL); + + if(lastfocus == (HWND)mp1 && currtime == lasttime) + { + if(count > 5) + { + count = 0; + return 1; + } + count++; + return 0; + } + + count = 0; + lastfocus = (HWND)mp1; + lasttime = currtime; + } + return 0; +} + /* Handles control messages sent to the box (owner). */ MRESULT EXPENTRY _controlproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) { @@ -1933,10 +2038,14 @@ break; } #endif + + if(_warp4_focus_fix(hWnd, msg, mp1, mp2)) + return (MRESULT)0; + if(msg == WM_SETFOCUS) + _toplevel_focus(hWnd); + if(blah && blah->oldproc) - { return blah->oldproc(hWnd, msg, mp1, mp2); - } return WinDefWindowProc(hWnd, msg, mp1, mp2); } @@ -2044,7 +2153,7 @@ WinQueryClassName(mybox->items[z].hwnd, 99, tmpbuf); /* If we have a notebook we resize the page again. */ - if(strncmp(tmpbuf, "#40", 3)==0) + if(strncmp(tmpbuf, "#40", 4)==0) { unsigned long x, y, width, height; int page = dw_notebook_page_query(mybox->items[z].hwnd); @@ -2131,6 +2240,10 @@ _free_window_memory(hWnd); break; } + + if(_warp4_focus_fix(hWnd, msg, mp1, mp2)) + return (MRESULT)0; + if(result != -1) return (MRESULT)result; else @@ -2673,7 +2786,7 @@ case WM_BUTTON2DOWN: case WM_BUTTON3DOWN: if(!res) - WinSetFocus(HWND_DESKTOP, hwnd); + _toplevel_focus(hwnd); return (MPARAM)TRUE; } return WinDefWindowProc(hwnd, msg, mp1, mp2); @@ -2756,16 +2869,16 @@ } /* - * Runs a message loop for Dynamic Windows, for a period of seconds. - * Parameters: - * seconds: Number of seconds to run the loop for. - */ -void dw_main_sleep(int seconds) + * Runs a message loop for Dynamic Windows, for a period of milliseconds. + * Parameters: + * milliseconds: Number of milliseconds to run the loop for. + */ +void dw_main_sleep(int milliseconds) { QMSG qmsg; - time_t start = time(NULL); - - while(time(NULL) - start <= seconds) + double start = (double)clock(); + + while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds) { if(WinPeekMsg(dwhab, &qmsg, 0, 0, 0, PM_NOREMOVE)) { @@ -3705,7 +3818,6 @@ NULL, NULL); dw_window_set_font(tmp, DefaultFont); - dw_window_set_font(tmp, DefaultFont); blah->oldproc = WinSubclassWindow(tmp, _comboentryproc); WinSetWindowPtr(tmp, QWP_USER, blah); return tmp; @@ -3952,13 +4064,40 @@ } /* + * Create a new slider window (widget) to be packed. + * Parameters: + * vertical: TRUE or FALSE if slider is vertical. + * increments: Number of increments available. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_slider_new(int vertical, int increments, ULONG id) +{ + WindowData *blah = calloc(1, sizeof(WindowData)); + SLDCDATA sldcData = { sizeof(SLDCDATA), increments, 0, 0, 0 }; + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_SLIDER, + "", + WS_VISIBLE | SLS_SNAPTOINCREMENT | + (vertical ? SLS_VERTICAL : SLS_HORIZONTAL), + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + &sldcData, + NULL); + + blah->oldproc = WinSubclassWindow(tmp, _entryproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + return tmp; +} + +/* * Create a new percent bar window (widget) to be packed. * Parameters: * id: An ID to be used with WinWindowFromID() or 0L. */ HWND dw_percent_new(ULONG id) { - WindowData *blah = calloc(1, sizeof(WindowData)); HWND tmp = WinCreateWindow(HWND_OBJECT, WC_SLIDER, "", @@ -3970,9 +4109,7 @@ id, NULL, NULL); - - blah->oldproc = WinSubclassWindow(tmp, _percentproc); - WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_disable(tmp); return tmp; } @@ -4178,7 +4315,6 @@ void dw_box_pack_end_stub(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) { - HWND boxowner = NULLHANDLE; Box *thisbox; if(WinWindowFromID(box, FID_CLIENT)) @@ -4243,13 +4379,8 @@ /* Don't set the ownership if it's an entryfield or spinbutton */ WinQueryClassName(item, 99, tmpbuf); - if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 3)!=0) - { - if((boxowner = WinQueryWindow(box, QW_OWNER)) != 0) - WinSetOwner(item, boxowner); - else - WinSetOwner(item, box); - } + if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0) + WinSetOwner(item, box); WinSetParent(item, box, FALSE); } } @@ -4822,7 +4953,7 @@ /* * Returns the range of the percent bar. * Parameters: - * handle: Handle to the slider to be queried. + * handle: Handle to the percent bar to be queried. */ unsigned int dw_percent_query_range(HWND handle) { @@ -4832,8 +4963,8 @@ /* * Sets the percent bar position. * Parameters: - * handle: Handle to the slider to be set. - * position: Position of the slider withing the range. + * handle: Handle to the percent bar to be set. + * position: Position of the percent bar withing the range. */ void dw_percent_set_pos(HWND handle, unsigned int position) { @@ -4841,6 +4972,27 @@ } /* + * Returns the position of the slider. + * Parameters: + * handle: Handle to the slider to be queried. + */ +unsigned int dw_slider_query_pos(HWND handle) +{ + return (unsigned int)WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); +} + +/* + * Sets the slider position. + * Parameters: + * handle: Handle to the slider to be set. + * position: Position of the slider withing the range. + */ +void dw_slider_set_pos(HWND handle, unsigned int position) +{ + WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)position); +} + +/* * Sets the spinbutton value. * Parameters: * handle: Handle to the spinbutton to be set. @@ -6160,12 +6312,25 @@ /* * Tries to gain access to the semaphore, if it can't it blocks. + * If we are in a callback we must keep the message loop running + * while blocking. * Parameters: * mutex: The handle to the mutex returned by dw_mutex_new(). */ void dw_mutex_lock(HMTX mutex) { - DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT); + if(_dwtid == dw_thread_id()) + { + int rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN); + + while(rc == ERROR_TIMEOUT) + { + dw_main_sleep(10); + rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN); + } + } + else + DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT); } /* @@ -6421,7 +6586,6 @@ void dw_box_pack_start_stub(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) { - HWND boxowner = NULLHANDLE; Box *thisbox; if(WinWindowFromID(box, FID_CLIENT)) @@ -6476,13 +6640,8 @@ WinQueryClassName(item, 99, tmpbuf); /* Don't set the ownership if it's an entryfield or spinbutton */ - if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 3)!=0) - { - if((boxowner = WinQueryWindow(box, QW_OWNER)) != 0) - WinSetOwner(item, boxowner); - else - WinSetOwner(item, box); - } + if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0) + WinSetOwner(item, box); WinSetParent(item, box, FALSE); } } diff -r 2be5174bdb5d -r a6801a2260af win/dw.c --- a/win/dw.c Sat Dec 08 04:47:43 2001 +0000 +++ b/win/dw.c Mon Jan 14 00:48:08 2002 +0000 @@ -2,7 +2,7 @@ * Dynamic Windows: * A GTK like implementation of the Win32 GUI * - * (C) 2000,2001 Brian Smith + * (C) 2000-2002 Brian Smith * */ #define _WIN32_IE 0x0500 @@ -26,6 +26,7 @@ HINSTANCE DWInstance = NULL; DWORD dwVersion = 0; +DWTID _dwtid = -1; /* I should probably check the actual file version, but this will do for now */ #define IS_WIN98PLUS (LOBYTE(LOWORD(dwVersion)) > 4 || \ @@ -101,7 +102,7 @@ static int in_checkbox_handler = 0; /* List of signals and their equivilent Win32 message */ -#define SIGNALMAX 14 +#define SIGNALMAX 15 SignalList SignalTranslate[SIGNALMAX] = { { WM_SIZE, "configure_event" }, @@ -117,7 +118,8 @@ { LBN_SELCHANGE, "item-select" }, { TVN_SELCHANGED, "tree-select" }, { WM_SETFOCUS, "set-focus" }, - { WM_USER+1, "lose-focus" } + { WM_USER+1, "lose-focus" }, + { WM_VSCROLL, "value_changed" } }; #ifdef BUILD_DLL @@ -324,12 +326,13 @@ /* These are the window classes which can * obtain input focus. */ - if(strnicmp(tmpbuf, EDITCLASSNAME, strlen(EDITCLASSNAME))==0 || /* Entryfield */ - strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME))==0 || /* Button */ - strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME))==0 || /* Combobox */ - strnicmp(tmpbuf, LISTBOXCLASSNAME, strlen(LISTBOXCLASSNAME))==0 || /* List box */ - strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS))==0 || /* Spinbutton */ - strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW))== 0) /* Container */ + if(strnicmp(tmpbuf, EDITCLASSNAME, strlen(EDITCLASSNAME)+1)==0 || /* Entryfield */ + strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0 || /* Button */ + strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0 || /* Combobox */ + strnicmp(tmpbuf, LISTBOXCLASSNAME, strlen(LISTBOXCLASSNAME)+1)==0 || /* List box */ + strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0 || /* Spinbutton */ + strnicmp(tmpbuf, TRACKBAR_CLASS, strlen(TRACKBAR_CLASS)+1)==0 || /* Slider */ + strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW)+1)== 0) /* Container */ return 1; return 0; } @@ -1164,6 +1167,8 @@ msg = WM_LBUTTONDOWN; if(msg == WM_RBUTTONUP || msg == WM_MBUTTONUP) msg = WM_LBUTTONUP; + if(msg == WM_HSCROLL) + msg = WM_VSCROLL; if(filterfunc) result = filterfunc(hWnd, msg, mp1, mp2); @@ -1412,6 +1417,33 @@ } } break; + case WM_HSCROLL: + case WM_VSCROLL: + { + char tmpbuf[100]; + HWND handle = (HWND)mp2; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, TRACKBAR_CLASS, strlen(TRACKBAR_CLASS)+1)==0) + { + int (*valuechangefunc)(HWND, int, void *) = tmp->signalfunction; + + if(handle == tmp->window) + { + int value = (int)SendMessage(handle, TBM_GETPOS, 0, 0); + int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); + ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); + + if(currentstyle & TBS_VERT) + result = valuechangefunc(tmp->window, max - value, tmp->data); + else + result = valuechangefunc(tmp->window, value, tmp->data); + tmp = NULL; + } + } + } + break; } } if(tmp) @@ -1779,6 +1811,10 @@ else _wndproc(hWnd, msg, mp1, mp2); break; + case WM_VSCROLL: + case WM_HSCROLL: + _wndproc(hWnd, msg, mp1, mp2); + break; case WM_CHAR: if(LOWORD(mp1) == '\t') { @@ -2702,6 +2738,8 @@ /* Setup the filter function */ filterfunc = func; + _dwtid = dw_thread_id(); + while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); @@ -2714,16 +2752,16 @@ } /* - * Runs a message loop for Dynamic Windows, for a period of seconds. - * Parameters: - * seconds: Number of seconds to run the loop for. - */ -void dw_main_sleep(int seconds) + * Runs a message loop for Dynamic Windows, for a period of milliseconds. + * Parameters: + * milliseconds: Number of milliseconds to run the loop for. + */ +void dw_main_sleep(int milliseconds) { MSG msg; - time_t start = time(NULL); - - while(time(NULL) - start <= seconds) + double start = (double)clock(); + + while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds) { if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { @@ -3602,17 +3640,18 @@ HWND dw_mle_new(ULONG id) { - HWND tmp = CreateWindow(EDITCLASSNAME, - "", - WS_BORDER | - WS_VSCROLL | ES_MULTILINE | - ES_WANTRETURN | WS_CHILD | - WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - NULL, - NULL); + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + EDITCLASSNAME, + "", + WS_BORDER | + WS_VSCROLL | ES_MULTILINE | + ES_WANTRETURN | WS_CHILD | + WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + NULL, + NULL); dw_window_set_font(tmp, DefaultFont); return tmp; } @@ -3625,16 +3664,17 @@ */ HWND dw_entryfield_new(char *text, ULONG id) { - HWND tmp = CreateWindow(EDITCLASSNAME, - text, - ES_WANTRETURN | WS_CHILD | - WS_BORDER | ES_AUTOHSCROLL | - WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - NULL, - NULL); + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + EDITCLASSNAME, + text, + ES_WANTRETURN | WS_CHILD | + WS_BORDER | ES_AUTOHSCROLL | + WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + NULL, + NULL); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); cinfo->back = cinfo->fore = -1; @@ -3654,16 +3694,17 @@ */ HWND dw_entryfield_password_new(char *text, ULONG id) { - HWND tmp = CreateWindow(EDITCLASSNAME, - text, - ES_WANTRETURN | WS_CHILD | - ES_PASSWORD | WS_BORDER | - ES_AUTOHSCROLL | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - NULL, - NULL); + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + EDITCLASSNAME, + text, + ES_WANTRETURN | WS_CHILD | + ES_PASSWORD | WS_BORDER | + ES_AUTOHSCROLL | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + NULL, + NULL); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); cinfo->back = cinfo->fore = -1; @@ -3795,32 +3836,30 @@ HWND dw_spinbutton_new(char *text, ULONG id) { ULONG *data = malloc(sizeof(ULONG)); - HWND buddy = CreateWindow(EDITCLASSNAME, - text, - WS_CHILD | WS_BORDER | - ES_NUMBER | WS_CLIPCHILDREN, + HWND buddy = CreateWindowEx(WS_EX_CLIENTEDGE, + EDITCLASSNAME, + text, + WS_CHILD | WS_BORDER | + ES_NUMBER | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + NULL, + NULL, + NULL); + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + UPDOWN_CLASS, + NULL, + WS_CHILD | UDS_ALIGNRIGHT | WS_BORDER | + UDS_ARROWKEYS | UDS_SETBUDDYINT | + UDS_WRAP | UDS_NOTHOUSANDS, 0,0,2000,1000, DW_HWND_OBJECT, - NULL, + (HMENU)id, NULL, NULL); - HWND tmp = CreateUpDownControl( - WS_CHILD | UDS_ALIGNRIGHT | - UDS_ARROWKEYS | UDS_SETBUDDYINT | - UDS_WRAP | UDS_NOTHOUSANDS, - 0, - 0, - 2000, - 1000, - DW_HWND_OBJECT, - id, - DWInstance, - buddy, - 0, - 100, - 0); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); + SendMessage(tmp, UDM_SETBUDDY, (WPARAM)buddy, 0); cinfo->back = cinfo->fore = -1; cinfo->buddy = tmp; @@ -3853,7 +3892,35 @@ (HMENU)id, NULL, NULL); - + BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); + bubble->id = id; + bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); + bubble->cinfo.fore = -1; + bubble->cinfo.back = -1; + SetWindowLong(tmp, GWL_USERDATA, (ULONG)bubble); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + + +/* + * Create a new slider window (widget) to be packed. + * Parameters: + * vertical: TRUE or FALSE if slider is vertical. + * increments: Number of increments available. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_slider_new(int vertical, int increments, ULONG id) +{ + HWND tmp = CreateWindow(TRACKBAR_CLASS, + "", + WS_CHILD | WS_CLIPCHILDREN | + (vertical ? TBS_VERT : TBS_HORZ), + 0,0,2000,1000, + DW_HWND_OBJECT, + NULL, + NULL, + NULL); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); cinfo->back = cinfo->fore = -1; @@ -3862,11 +3929,10 @@ cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); SetWindowLong(tmp, GWL_USERDATA, (ULONG)cinfo); - dw_window_set_font(tmp, DefaultFont); + SendMessage(tmp, TBM_SETRANGE, (WPARAM)FALSE, (LPARAM)MAKELONG(0, increments-1)); return tmp; } - /* * Create a new percent bar window (widget) to be packed. * Parameters: @@ -4889,7 +4955,7 @@ /* * Returns the range of the percent bar. * Parameters: - * handle: Handle to the slider to be queried. + * handle: Handle to the percent bar to be queried. */ unsigned int dw_percent_query_range(HWND handle) { @@ -4899,8 +4965,8 @@ /* * Sets the percent bar position. * Parameters: - * handle: Handle to the slider to be set. - * position: Position of the slider withing the range. + * handle: Handle to the percent bar to be set. + * position: Position of the percent bar withing the range. */ void dw_percent_set_pos(HWND handle, unsigned int position) { @@ -4908,6 +4974,38 @@ } /* + * Returns the position of the slider. + * Parameters: + * handle: Handle to the slider to be queried. + */ +unsigned int dw_slider_query_pos(HWND handle) +{ + int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); + ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); + + if(currentstyle & TBS_VERT) + return max - (unsigned int)SendMessage(handle, TBM_GETPOS, 0, 0); + return (unsigned int)SendMessage(handle, TBM_GETPOS, 0, 0); +} + +/* + * Sets the slider position. + * Parameters: + * handle: Handle to the slider to be set. + * position: Position of the slider withing the range. + */ +void dw_slider_set_pos(HWND handle, unsigned int position) +{ + int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); + ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); + + if(currentstyle & TBS_VERT) + SendMessage(handle, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)max - position); + else + SendMessage(handle, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)position); +} + +/* * Sets the spinbutton value. * Parameters: * handle: Handle to the spinbutton to be set. @@ -4981,6 +5079,22 @@ return (in_checkbox_handler ? TRUE : FALSE); } +/* This function unchecks all radiobuttons on a box */ +BOOL CALLBACK _uncheck_radios(HWND handle, LPARAM lParam) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0) + { + BubbleButton *bubble= (BubbleButton *)GetWindowLong(handle, GWL_USERDATA); + + if(bubble && !bubble->checkbox) + SendMessage(handle, BM_SETCHECK, 0, 0); + } + return TRUE; +} /* * Sets the state of the checkbox. * Parameters: @@ -4989,10 +5103,15 @@ */ void dw_checkbox_set(HWND handle, int value) { - ColorInfo *cinfo = (ColorInfo *)GetWindowLong(handle, GWL_USERDATA); - - if(cinfo && !cinfo->user) - SendMessage(handle, BM_CLICK, 0, 0); + BubbleButton *bubble= (BubbleButton *)GetWindowLong(handle, GWL_USERDATA); + + if(bubble && !bubble->checkbox) + { + HWND parent = GetParent(handle); + + if(parent) + EnumChildWindows(parent, _uncheck_radios, 0); + } SendMessage(handle, BM_SETCHECK, (WPARAM)value, 0); } @@ -6056,7 +6175,18 @@ */ void dw_mutex_lock(HMTX mutex) { - WaitForSingleObject((HANDLE)mutex, INFINITE); + if(_dwtid == dw_thread_id()) + { + int rc = WaitForSingleObject((HANDLE)mutex, 0); + + while(rc == WAIT_TIMEOUT) + { + dw_main_sleep(1); + rc = WaitForSingleObject((HANDLE)mutex, 0); + } + } + else + WaitForSingleObject((HANDLE)mutex, INFINITE); } /*