Mercurial > dwindows
comparison gtk4/dw.c @ 2268:fefeb5b4e512
GTK4: Complete refactoring of the signal system to be more simple and
flexible. Divide the setup into class specific functions.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Sun, 31 Jan 2021 11:57:06 +0000 |
parents | 7ac85e938b71 |
children | a26cfd4bbffe |
comparison
equal
deleted
inserted
replaced
2267:7ac85e938b71 | 2268:fefeb5b4e512 |
---|---|
100 pthread_key_t _dw_fg_color_key; | 100 pthread_key_t _dw_fg_color_key; |
101 pthread_key_t _dw_bg_color_key; | 101 pthread_key_t _dw_bg_color_key; |
102 | 102 |
103 GtkWidget *last_window = NULL, *popup = NULL; | 103 GtkWidget *last_window = NULL, *popup = NULL; |
104 | 104 |
105 static int _dw_ignore_click = 0, _dw_ignore_expand = 0; | 105 static int _dw_ignore_expand = 0; |
106 static pthread_t _dw_thread = (pthread_t)-1; | 106 static pthread_t _dw_thread = (pthread_t)-1; |
107 | 107 |
108 #define DEFAULT_SIZE_WIDTH 12 | 108 #define DEFAULT_SIZE_WIDTH 12 |
109 #define DEFAULT_SIZE_HEIGHT 6 | 109 #define DEFAULT_SIZE_HEIGHT 6 |
110 #define DEFAULT_TITLEBAR_HEIGHT 22 | 110 #define DEFAULT_TITLEBAR_HEIGHT 22 |
120 static gint _motion_notify_event(GtkEventControllerMotion *controller, double x, double y, gpointer data); | 120 static gint _motion_notify_event(GtkEventControllerMotion *controller, double x, double y, gpointer data); |
121 static gint _delete_event(GtkWidget *widget, gpointer data); | 121 static gint _delete_event(GtkWidget *widget, gpointer data); |
122 static gint _key_press_event(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer data); | 122 static gint _key_press_event(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer data); |
123 static gint _generic_event(GtkWidget *widget, gpointer data); | 123 static gint _generic_event(GtkWidget *widget, gpointer data); |
124 static gint _configure_event(GtkWidget *widget, GdkEvent *event, gpointer data); | 124 static gint _configure_event(GtkWidget *widget, GdkEvent *event, gpointer data); |
125 static gint _activate_event(GtkWidget *widget, gpointer data); | |
126 static gint _container_enter_event(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer data); | 125 static gint _container_enter_event(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer data); |
127 static gint _combobox_select_event(GtkWidget *widget, gpointer data); | 126 static gint _combobox_select_event(GtkWidget *widget, gpointer data); |
128 static gint _expose_event(GtkWidget *widget, cairo_t *cr, gpointer data); | 127 static gint _expose_event(GtkWidget *widget, cairo_t *cr, gpointer data); |
129 static gint _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data); | 128 static gint _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data); |
130 static gint _tree_context_event(GtkWidget *widget, GdkEvent *event, gpointer data); | 129 static gint _tree_context_event(GtkWidget *widget, GdkEvent *event, gpointer data); |
144 GMainLoop *_DWMainLoop = NULL; | 143 GMainLoop *_DWMainLoop = NULL; |
145 static char _dw_app_id[_DW_APP_ID_SIZE+1] = { 0 }; | 144 static char _dw_app_id[_DW_APP_ID_SIZE+1] = { 0 }; |
146 char *_DWDefaultFont = NULL; | 145 char *_DWDefaultFont = NULL; |
147 static char _dw_share_path[PATH_MAX+1] = { 0 }; | 146 static char _dw_share_path[PATH_MAX+1] = { 0 }; |
148 | 147 |
149 typedef struct | 148 typedef struct _dw_signal_list |
150 { | 149 { |
151 void *func; | 150 void *func; |
152 char name[30]; | 151 char name[30]; |
152 char gname[30]; | |
153 GObject *(*setup)(struct _dw_signal_list *, GObject *, void *[], void *, void *, void *); | |
153 | 154 |
154 } SignalList; | 155 } SignalList; |
156 | |
157 /* Signal setup function prototypes */ | |
158 GObject *_dw_key_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
159 GObject *_dw_button_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
160 GObject *_dw_motion_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
161 GObject *_dw_draw_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
162 GObject *_dw_value_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
163 GObject *_dw_list_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
164 GObject *_dw_tree_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
165 GObject *_dw_focus_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
166 GObject *_dw_html_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data); | |
155 | 167 |
156 typedef struct | 168 typedef struct |
157 { | 169 { |
158 HWND window; | 170 HWND window; |
159 void *func; | 171 void *func; |
161 gint cid; | 173 gint cid; |
162 void *intfunc; | 174 void *intfunc; |
163 | 175 |
164 } SignalHandler; | 176 } SignalHandler; |
165 | 177 |
166 #define SIGNALMAX 20 | |
167 | |
168 /* A list of signal forwarders, to account for paramater differences. */ | 178 /* A list of signal forwarders, to account for paramater differences. */ |
169 static SignalList SignalTranslate[SIGNALMAX] = { | 179 static SignalList SignalTranslate[] = { |
170 { _configure_event, DW_SIGNAL_CONFIGURE }, | 180 { _configure_event, DW_SIGNAL_CONFIGURE, "resize", NULL }, |
171 { _key_press_event, DW_SIGNAL_KEY_PRESS }, | 181 { _key_press_event, DW_SIGNAL_KEY_PRESS, "key-pressed", _dw_key_setup }, |
172 { _button_press_event, DW_SIGNAL_BUTTON_PRESS }, | 182 { _button_press_event, DW_SIGNAL_BUTTON_PRESS, "pressed", _dw_button_setup }, |
173 { _button_release_event, DW_SIGNAL_BUTTON_RELEASE }, | 183 { _button_release_event, DW_SIGNAL_BUTTON_RELEASE, "released", _dw_button_setup }, |
174 { _motion_notify_event, DW_SIGNAL_MOTION_NOTIFY }, | 184 { _motion_notify_event, DW_SIGNAL_MOTION_NOTIFY, "motion", _dw_motion_setup }, |
175 { _delete_event, DW_SIGNAL_DELETE }, | 185 { _delete_event, DW_SIGNAL_DELETE, "close-request", NULL }, |
176 { _expose_event, DW_SIGNAL_EXPOSE }, | 186 { _expose_event, DW_SIGNAL_EXPOSE, "draw", _dw_draw_setup }, |
177 { _activate_event, "activate" }, | 187 { _generic_event, DW_SIGNAL_CLICKED, "pressed", _dw_button_setup }, |
178 { _generic_event, DW_SIGNAL_CLICKED }, | 188 { _container_enter_event, DW_SIGNAL_ITEM_ENTER, "key-pressed", _dw_key_setup }, |
179 { _container_enter_event, DW_SIGNAL_ITEM_ENTER }, | 189 { _tree_context_event, DW_SIGNAL_ITEM_CONTEXT, "pressed", _dw_tree_setup }, |
180 { _tree_context_event, DW_SIGNAL_ITEM_CONTEXT }, | 190 { _combobox_select_event, DW_SIGNAL_LIST_SELECT, "changed", _dw_list_setup }, |
181 { _combobox_select_event, DW_SIGNAL_LIST_SELECT }, | 191 { _tree_select_event, DW_SIGNAL_ITEM_SELECT, "row-activated", _dw_list_setup }, |
182 { _tree_select_event, DW_SIGNAL_ITEM_SELECT }, | 192 { _set_focus_event, DW_SIGNAL_SET_FOCUS, "activate-focus", _dw_focus_setup }, |
183 { _set_focus_event, DW_SIGNAL_SET_FOCUS }, | 193 { _value_changed_event, DW_SIGNAL_VALUE_CHANGED, "value-changed", _dw_value_setup }, |
184 { _value_changed_event, DW_SIGNAL_VALUE_CHANGED }, | 194 { _switch_page_event, DW_SIGNAL_SWITCH_PAGE, "switch-page", NULL }, |
185 { _switch_page_event, DW_SIGNAL_SWITCH_PAGE }, | 195 { _column_click_event, DW_SIGNAL_COLUMN_CLICK, "activate", _dw_tree_setup }, |
186 { _column_click_event, DW_SIGNAL_COLUMN_CLICK }, | 196 { _tree_expand_event, DW_SIGNAL_TREE_EXPAND, "row-expanded", NULL }, |
187 { _tree_expand_event, DW_SIGNAL_TREE_EXPAND }, | |
188 #ifdef USE_WEBKIT | 197 #ifdef USE_WEBKIT |
189 { _html_changed_event, DW_SIGNAL_HTML_CHANGED }, | 198 { _html_changed_event, DW_SIGNAL_HTML_CHANGED, "load-changed", NULL }, |
190 #else | |
191 { _generic_event, DW_SIGNAL_HTML_CHANGED }, | |
192 #endif | 199 #endif |
193 { _html_result_event, DW_SIGNAL_HTML_RESULT } | 200 { _html_result_event, DW_SIGNAL_HTML_RESULT, "", _dw_html_setup }, |
201 { NULL, "", "", NULL } | |
194 }; | 202 }; |
195 | 203 |
196 /* Alignment flags */ | 204 /* Alignment flags */ |
197 #define DW_CENTER 0.5f | 205 #define DW_CENTER 0.5f |
198 #define DW_LEFT 0.0f | 206 #define DW_LEFT 0.0f |
219 usleep(period * 1000); | 227 usleep(period * 1000); |
220 #endif | 228 #endif |
221 } | 229 } |
222 | 230 |
223 /* Finds the translation function for a given signal name */ | 231 /* Finds the translation function for a given signal name */ |
224 static void *_findsigfunc(const char *signame) | 232 static SignalList *_dw_findsignal(const char *signame) |
225 { | 233 { |
226 int z; | 234 int z=0; |
227 | 235 |
228 for(z=0;z<SIGNALMAX;z++) | 236 while(SignalTranslate[z].func) |
229 { | 237 { |
230 if(strcasecmp(signame, SignalTranslate[z].name) == 0) | 238 if(strcasecmp(signame, SignalTranslate[z].name) == 0) |
231 return SignalTranslate[z].func; | 239 return &SignalTranslate[z]; |
240 z++; | |
232 } | 241 } |
233 return NULL; | 242 return NULL; |
234 } | 243 } |
235 | 244 |
236 static SignalHandler _get_signal_handler(gpointer data) | 245 static SignalHandler _get_signal_handler(gpointer data) |
275 g_object_set_data(G_OBJECT(widget), text, NULL); | 284 g_object_set_data(G_OBJECT(widget), text, NULL); |
276 sprintf(text, "_dw_sigdata%d", counter); | 285 sprintf(text, "_dw_sigdata%d", counter); |
277 g_object_set_data(G_OBJECT(widget), text, NULL); | 286 g_object_set_data(G_OBJECT(widget), text, NULL); |
278 } | 287 } |
279 | 288 |
280 static int _set_signal_handler(GtkWidget *widget, HWND window, void *func, gpointer data, void *intfunc, void *discfunc) | 289 static int _set_signal_handler(GObject *object, HWND window, void *func, gpointer data, void *intfunc, void *discfunc) |
281 { | 290 { |
282 int counter = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "_dw_sigcounter")); | 291 int counter = GPOINTER_TO_INT(g_object_get_data(object, "_dw_sigcounter")); |
283 char text[100]; | 292 char text[100]; |
284 | 293 |
285 sprintf(text, "_dw_sigwindow%d", counter); | 294 sprintf(text, "_dw_sigwindow%d", counter); |
286 g_object_set_data(G_OBJECT(widget), text, (gpointer)window); | 295 g_object_set_data(object, text, (gpointer)window); |
287 sprintf(text, "_dw_sigfunc%d", counter); | 296 sprintf(text, "_dw_sigfunc%d", counter); |
288 g_object_set_data(G_OBJECT(widget), text, (gpointer)func); | 297 g_object_set_data(object, text, (gpointer)func); |
289 sprintf(text, "_dw_intfunc%d", counter); | 298 sprintf(text, "_dw_intfunc%d", counter); |
290 g_object_set_data(G_OBJECT(widget), text, (gpointer)intfunc); | 299 g_object_set_data(object, text, (gpointer)intfunc); |
291 sprintf(text, "_dw_discfunc%d", counter); | 300 sprintf(text, "_dw_discfunc%d", counter); |
292 g_object_set_data(G_OBJECT(widget), text, (gpointer)discfunc); | 301 g_object_set_data(object, text, (gpointer)discfunc); |
293 sprintf(text, "_dw_sigdata%d", counter); | 302 sprintf(text, "_dw_sigdata%d", counter); |
294 g_object_set_data(G_OBJECT(widget), text, (gpointer)data); | 303 g_object_set_data(object, text, (gpointer)data); |
295 | 304 |
296 counter++; | 305 counter++; |
297 g_object_set_data(G_OBJECT(widget), "_dw_sigcounter", GINT_TO_POINTER(counter)); | 306 g_object_set_data(object, "_dw_sigcounter", GINT_TO_POINTER(counter)); |
298 | 307 |
299 return counter - 1; | 308 return counter - 1; |
300 } | 309 } |
301 | 310 |
302 static void _set_signal_handler_id(GtkWidget *widget, int counter, gint cid) | 311 static void _set_signal_handler_id(GObject *object, int counter, gint cid) |
303 { | 312 { |
304 char text[100]; | 313 char text[100]; |
305 | 314 |
306 sprintf(text, "_dw_sigcid%d", counter); | 315 sprintf(text, "_dw_sigcid%d", counter); |
307 g_object_set_data(G_OBJECT(widget), text, GINT_TO_POINTER(cid)); | 316 g_object_set_data(object, text, GINT_TO_POINTER(cid)); |
308 } | 317 } |
309 | 318 |
310 static void _html_result_event(GObject *object, GAsyncResult *result, gpointer script_data) | 319 static void _html_result_event(GObject *object, GAsyncResult *result, gpointer script_data) |
311 { | 320 { |
312 #ifdef USE_WEBKIT | 321 #ifdef USE_WEBKIT |
519 if(work.window) | 528 if(work.window) |
520 { | 529 { |
521 int (*genericfunc)(HWND, void *) = work.func; | 530 int (*genericfunc)(HWND, void *) = work.func; |
522 | 531 |
523 retval = genericfunc(work.window, work.data); | 532 retval = genericfunc(work.window, work.data); |
524 } | |
525 return retval; | |
526 } | |
527 | |
528 static gint _activate_event(GtkWidget *widget, gpointer data) | |
529 { | |
530 SignalHandler work = _get_signal_handler(data); | |
531 int retval = FALSE; | |
532 | |
533 if(work.window && !_dw_ignore_click) | |
534 { | |
535 int (*activatefunc)(HWND, void *) = work.func; | |
536 | |
537 retval = activatefunc(popup ? popup : work.window, work.data); | |
538 popup = NULL; | |
539 } | 533 } |
540 return retval; | 534 return retval; |
541 } | 535 } |
542 | 536 |
543 static gint _configure_event(GtkWidget *widget, GdkEvent *event, gpointer data) | 537 static gint _configure_event(GtkWidget *widget, GdkEvent *event, gpointer data) |
3812 * Parameters: | 3806 * Parameters: |
3813 * handle: Handle to the checkbox to be queried. | 3807 * handle: Handle to the checkbox to be queried. |
3814 */ | 3808 */ |
3815 int dw_checkbox_get(HWND handle) | 3809 int dw_checkbox_get(HWND handle) |
3816 { | 3810 { |
3817 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(handle)); | 3811 if(GTK_IS_TOGGLE_BUTTON(handle)) |
3812 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(handle)); | |
3813 return gtk_check_button_get_active(GTK_CHECK_BUTTON(handle)); | |
3818 } | 3814 } |
3819 | 3815 |
3820 /* | 3816 /* |
3821 * Sets the state of the checkbox. | 3817 * Sets the state of the checkbox. |
3822 * Parameters: | 3818 * Parameters: |
3823 * handle: Handle to the checkbox to be queried. | 3819 * handle: Handle to the checkbox to be queried. |
3824 * value: TRUE for checked, FALSE for unchecked. | 3820 * value: TRUE for checked, FALSE for unchecked. |
3825 */ | 3821 */ |
3826 void dw_checkbox_set(HWND handle, int value) | 3822 void dw_checkbox_set(HWND handle, int value) |
3827 { | 3823 { |
3828 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(handle), value); | 3824 if(GTK_IS_TOGGLE_BUTTON(handle)) |
3825 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(handle), value); | |
3826 else | |
3827 gtk_check_button_set_active(GTK_CHECK_BUTTON(handle), value); | |
3829 } | 3828 } |
3830 | 3829 |
3831 /* | 3830 /* |
3832 * Inserts an item into a tree window (widget) after another item. | 3831 * Inserts an item into a tree window (widget) after another item. |
3833 * Parameters: | 3832 * Parameters: |
9499 } | 9498 } |
9500 } | 9499 } |
9501 | 9500 |
9502 #define _DW_INTERNAL_CALLBACK_PARAMS 4 | 9501 #define _DW_INTERNAL_CALLBACK_PARAMS 4 |
9503 | 9502 |
9503 /* Signal setup functions */ | |
9504 GObject *_dw_key_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9505 { | |
9506 if(GTK_IS_WIDGET(object)) | |
9507 { | |
9508 GtkEventController *controller = gtk_event_controller_key_new(); | |
9509 gtk_widget_add_controller(GTK_WIDGET(object), controller); | |
9510 return G_OBJECT(controller); | |
9511 } | |
9512 return object; | |
9513 } | |
9514 | |
9515 GObject *_dw_button_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9516 { | |
9517 /* Special case for handling notification signals, which aren't really signals */ | |
9518 if(G_IS_NOTIFICATION(object) && strcmp(signal->name, DW_SIGNAL_CLICKED) == 0) | |
9519 { | |
9520 char textbuf[101] = {0}; | |
9521 snprintf(textbuf, 100, "dw-notification-%llu-func", DW_POINTER_TO_ULONGLONG(object)); | |
9522 g_object_set_data(G_OBJECT(_DWApp), textbuf, DW_POINTER(sigfunc)); | |
9523 snprintf(textbuf, 100, "dw-notification-%llu-data", DW_POINTER_TO_ULONGLONG(object)); | |
9524 g_object_set_data(G_OBJECT(_DWApp), textbuf, DW_POINTER(data)); | |
9525 return NULL; | |
9526 } | |
9527 else if(GTK_IS_WIDGET(object)) | |
9528 { | |
9529 GtkGesture *gesture = gtk_gesture_click_new(); | |
9530 gtk_widget_add_controller(GTK_WIDGET(object), GTK_EVENT_CONTROLLER(gesture)); | |
9531 return G_OBJECT(gesture); | |
9532 } | |
9533 return object; | |
9534 } | |
9535 | |
9536 GObject *_dw_motion_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9537 { | |
9538 if(GTK_IS_WIDGET(object)) | |
9539 { | |
9540 GtkEventController *controller = gtk_event_controller_motion_new(); | |
9541 gtk_widget_add_controller(GTK_WIDGET(object), controller); | |
9542 return G_OBJECT(controller); | |
9543 } | |
9544 return object; | |
9545 } | |
9546 | |
9547 GObject *_dw_draw_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9548 { | |
9549 if(GTK_IS_DRAWING_AREA(object)) | |
9550 { | |
9551 /* TODO: Might need to use the disconnect paramater since this isn't a normal signal handler */ | |
9552 gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(object), signal->func, data, NULL); | |
9553 _set_signal_handler(object, (HWND)object, sigfunc, data, signal->func, discfunc); | |
9554 return NULL; | |
9555 } | |
9556 return object; | |
9557 } | |
9558 | |
9559 GObject *_dw_tree_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9560 { | |
9561 if(GTK_IS_TREE_VIEW(object)) | |
9562 { | |
9563 if(strcmp(signal->name, DW_SIGNAL_COLUMN_CLICK) == 0) | |
9564 { | |
9565 /* We don't actually need a signal handler here... just need to assign the handler ID | |
9566 * Since the handlers for the columns were already created in _dw_container_setup() | |
9567 */ | |
9568 int sigid = _set_signal_handler(object, (HWND)object, sigfunc, data, signal->func, discfunc); | |
9569 g_object_set_data(object, "_dw_column_click_id", GINT_TO_POINTER(sigid+1)); | |
9570 return NULL; | |
9571 } | |
9572 else | |
9573 { | |
9574 GtkGesture *gesture = gtk_gesture_click_new(); | |
9575 gtk_widget_add_controller(GTK_WIDGET(object), GTK_EVENT_CONTROLLER(gesture)); | |
9576 return G_OBJECT(gesture); | |
9577 } | |
9578 } | |
9579 return object; | |
9580 } | |
9581 | |
9582 GObject *_dw_list_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9583 { | |
9584 if((GTK_IS_TREE_VIEW(object) && strcmp(signal->name, DW_SIGNAL_ITEM_SELECT) == 0) || | |
9585 (GTK_IS_COMBO_BOX(object) && strcmp(signal->name, DW_SIGNAL_LIST_SELECT) == 0)) | |
9586 { | |
9587 /* TODO: Might need to allocate a new "params" here */ | |
9588 int cid, sigid = _set_signal_handler(object, (HWND)object, sigfunc, data, signal->func, discfunc); | |
9589 params[0] = DW_INT_TO_POINTER(sigid); | |
9590 params[2] = DW_POINTER(object); | |
9591 if(GTK_IS_TREE_VIEW(object)) | |
9592 cid = g_signal_connect_data(object, signal->gname, G_CALLBACK(signal->func), params, _dw_signal_disconnect, 0); | |
9593 else | |
9594 cid = g_signal_connect_data(object, signal->gname, G_CALLBACK(_combobox_select_event), params, _dw_signal_disconnect, 0); | |
9595 _set_signal_handler_id(object, sigid, cid); | |
9596 return NULL; | |
9597 } | |
9598 return object; | |
9599 } | |
9600 | |
9601 GObject *_dw_value_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9602 { | |
9603 if(GTK_IS_SCALE(object) || GTK_IS_SCROLLBAR(object) || GTK_IS_SPIN_BUTTON(object)) | |
9604 return G_OBJECT(g_object_get_data(object, "_dw_adjustment")); | |
9605 return object; | |
9606 } | |
9607 | |
9608 GObject *_dw_focus_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9609 { | |
9610 if(GTK_IS_COMBO_BOX(object) && strcmp(signal->name, DW_SIGNAL_SET_FOCUS) == 0) | |
9611 return G_OBJECT(gtk_combo_box_get_child(GTK_COMBO_BOX(object))); | |
9612 return object; | |
9613 } | |
9614 | |
9615 GObject *_dw_html_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) | |
9616 { | |
9617 #ifdef USE_WEBKIT | |
9618 if(WEBKIT_IS_WEB_VIEW(object) && strcmp(signal->name, DW_SIGNAL_HTML_RESULT) == 0) | |
9619 { | |
9620 /* We don't actually need a signal handler here... just need to assign the handler ID | |
9621 * Since the handler is created in dw_html_javasript_run() | |
9622 */ | |
9623 int sigid = _set_signal_handler(object, (HWND)object, sigfunc, data, signal->func, discfunc); | |
9624 g_object_set_data(object, "_dw_html_result_id", GINT_TO_POINTER(sigid+1)); | |
9625 return NULL; | |
9626 } | |
9627 #endif | |
9628 return object; | |
9629 } | |
9630 | |
9504 /* | 9631 /* |
9505 * Add a callback to a window event with a closure callback. | 9632 * Add a callback to a window event with a closure callback. |
9506 * Parameters: | 9633 * Parameters: |
9507 * window: Window handle of signal to be called back. | 9634 * window: Window handle of signal to be called back. |
9508 * signame: A string pointer identifying which signal to be hooked. | 9635 * signame: A string pointer identifying which signal to be hooked. |
9510 * discfunc: The pointer to the function called when this handler is removed. | 9637 * discfunc: The pointer to the function called when this handler is removed. |
9511 * data: User data to be passed to the handler function. | 9638 * data: User data to be passed to the handler function. |
9512 */ | 9639 */ |
9513 void dw_signal_connect_data(HWND window, const char *signame, void *sigfunc, void *discfunc, void *data) | 9640 void dw_signal_connect_data(HWND window, const char *signame, void *sigfunc, void *discfunc, void *data) |
9514 { | 9641 { |
9515 void *thisfunc = _findsigfunc(signame); | 9642 SignalList *signal = _dw_findsignal(signame); |
9516 char *thisname = (char *)signame; | 9643 |
9517 HWND thiswindow = window; | 9644 if(signal && signal->func) |
9518 int sigid; | 9645 { |
9519 void **params = calloc(_DW_INTERNAL_CALLBACK_PARAMS, sizeof(void *)); | 9646 GObject *object = (GObject *)window; |
9520 gint cid; | 9647 void **params = calloc(_DW_INTERNAL_CALLBACK_PARAMS, sizeof(void *)); |
9521 | 9648 int sigid; |
9522 /* Save the disconnect function pointer */ | 9649 gint cid; |
9523 params[1] = discfunc; | 9650 |
9524 | 9651 /* Save the disconnect function pointer */ |
9525 /* Special case for handling notification signals, which aren't really signals */ | 9652 params[1] = discfunc; |
9526 if (G_IS_NOTIFICATION(thiswindow) && strcmp(signame, DW_SIGNAL_CLICKED) == 0) | 9653 |
9527 { | 9654 /* |
9528 char textbuf[101] = {0}; | 9655 * If the window we are setting the signal on is a scrolled window we need to get |
9529 snprintf(textbuf, 100, "dw-notification-%llu-func", DW_POINTER_TO_ULONGLONG(thiswindow)); | 9656 * the "real" widget type. thiswindow is the "real" widget type |
9530 g_object_set_data(G_OBJECT(_DWApp), textbuf, DW_POINTER(sigfunc)); | |
9531 snprintf(textbuf, 100, "dw-notification-%llu-data", DW_POINTER_TO_ULONGLONG(thiswindow)); | |
9532 g_object_set_data(G_OBJECT(_DWApp), textbuf, DW_POINTER(data)); | |
9533 return; | |
9534 } | |
9535 /* | |
9536 * If the window we are setting the signal on is a scrolled window we need to get | |
9537 * the "real" widget type. thiswindow is the "real" widget type | |
9538 */ | |
9539 if (GTK_IS_SCROLLED_WINDOW(thiswindow) | |
9540 #ifdef USE_WEBKIT | |
9541 && !(thiswindow = (HWND)_dw_html_web_view(thiswindow)) | |
9542 #endif | |
9543 ) | |
9544 { | |
9545 thiswindow = (HWND)g_object_get_data(G_OBJECT(window), "_dw_user"); | |
9546 } | |
9547 | |
9548 if (strcmp(signame, DW_SIGNAL_EXPOSE) == 0) | |
9549 { | |
9550 thisname = "draw"; | |
9551 } | |
9552 /* TODO: Convert to GMenuModel */ | |
9553 #if GTK3 | |
9554 else if (GTK_IS_MENU_ITEM(thiswindow) && strcmp(signame, DW_SIGNAL_CLICKED) == 0) | |
9555 { | |
9556 thisname = "activate"; | |
9557 thisfunc = _findsigfunc(thisname); | |
9558 } | |
9559 #endif | |
9560 else if (GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_CONTEXT) == 0) | |
9561 { | |
9562 //GtkGesture *gesture = gtk_gesture_click_new(); | |
9563 sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc, discfunc); | |
9564 params[0] = GINT_TO_POINTER(sigid); | |
9565 params[2] = (void *)thiswindow; | |
9566 cid = g_signal_connect_data(G_OBJECT(thiswindow), "button_press_event", G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0); | |
9567 _set_signal_handler_id(thiswindow, sigid, cid); | |
9568 return; | |
9569 } | |
9570 else if ((GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_SELECT) == 0) || | |
9571 (GTK_IS_COMBO_BOX(thiswindow) && strcmp(signame, DW_SIGNAL_LIST_SELECT) == 0)) | |
9572 { | |
9573 GtkWidget *widget = thiswindow; | |
9574 | |
9575 thisname = "changed"; | |
9576 | |
9577 sigid = _set_signal_handler(widget, window, sigfunc, data, thisfunc, discfunc); | |
9578 params[0] = GINT_TO_POINTER(sigid); | |
9579 params[2] = (void *)thiswindow; | |
9580 if(GTK_IS_TREE_VIEW(thiswindow)) | |
9581 { | |
9582 thiswindow = (GtkWidget *)gtk_tree_view_get_selection(GTK_TREE_VIEW(thiswindow)); | |
9583 cid = g_signal_connect_data(G_OBJECT(thiswindow), thisname, G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0); | |
9584 } | |
9585 else | |
9586 { | |
9587 cid = g_signal_connect_data(G_OBJECT(thiswindow), thisname, G_CALLBACK(_combobox_select_event), params, _dw_signal_disconnect, 0); | |
9588 } | |
9589 _set_signal_handler_id(widget, sigid, cid); | |
9590 return; | |
9591 } | |
9592 else if (GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_TREE_EXPAND) == 0) | |
9593 { | |
9594 thisname = "row-expanded"; | |
9595 } | |
9596 else if (GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_ENTER) == 0) | |
9597 { | |
9598 GtkEventController *controller = gtk_event_controller_key_new(); | |
9599 sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _container_enter_event, discfunc); | |
9600 params[0] = GINT_TO_POINTER(sigid); | |
9601 params[2] = (void *)thiswindow; | |
9602 gtk_widget_add_controller(GTK_WIDGET(thiswindow), controller); | |
9603 cid = g_signal_connect_data(G_OBJECT(controller), "key-pressed", G_CALLBACK(_container_enter_event), params, _dw_signal_disconnect, 0); | |
9604 _set_signal_handler_id(thiswindow, sigid, cid); | |
9605 | |
9606 params = calloc(sizeof(void *), _DW_INTERNAL_CALLBACK_PARAMS); | |
9607 | |
9608 thisname = "button_press_event"; | |
9609 thisfunc = _findsigfunc(DW_SIGNAL_ITEM_ENTER); | |
9610 } | |
9611 else if (GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_COLUMN_CLICK) == 0) | |
9612 { | |
9613 /* We don't actually need a signal handler here... just need to assign the handler ID | |
9614 * Since the handlers for the columns were already created in _dw_container_setup() | |
9615 */ | 9657 */ |
9616 sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _column_click_event, discfunc); | 9658 if (GTK_IS_SCROLLED_WINDOW(window) |
9617 g_object_set_data(G_OBJECT(thiswindow), "_dw_column_click_id", GINT_TO_POINTER(sigid+1)); | 9659 #ifdef USE_WEBKIT |
9618 return; | 9660 && !(object = G_OBJECT(_dw_html_web_view(window))) |
9619 } | 9661 #endif |
9620 else if (strcmp(signame, DW_SIGNAL_SET_FOCUS) == 0) | 9662 ) |
9621 { | 9663 object = (GObject *)g_object_get_data(G_OBJECT(window), "_dw_user"); |
9622 thisname = "focus-in-event"; | 9664 |
9623 if (GTK_IS_COMBO_BOX(thiswindow)) | 9665 /* Do object class specific setup */ |
9624 thiswindow = gtk_combo_box_get_child(GTK_COMBO_BOX(thiswindow)); | 9666 if(signal->setup) |
9625 } | 9667 object = signal->setup(signal, object, params, sigfunc, discfunc, data); |
9626 #ifdef USE_WEBKIT | 9668 |
9627 else if (WEBKIT_IS_WEB_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_HTML_CHANGED) == 0) | 9669 if(!object) |
9628 { | 9670 { |
9629 thisname = "load-changed"; | 9671 free(params); |
9630 } | 9672 return; |
9631 else if (WEBKIT_IS_WEB_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_HTML_RESULT) == 0) | 9673 } |
9632 { | 9674 |
9633 /* We don't actually need a signal handler here... just need to assign the handler ID | 9675 sigid = _set_signal_handler(object, window, sigfunc, data, signal->func, discfunc); |
9634 * Since the handler is created in dw_html_javasript_run() | 9676 params[0] = DW_INT_TO_POINTER(sigid); |
9635 */ | 9677 params[2] = DW_POINTER(object); |
9636 sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _html_result_event, discfunc); | 9678 cid = g_signal_connect_data(object, signal->gname, G_CALLBACK(signal->func), params, _dw_signal_disconnect, 0); |
9637 g_object_set_data(G_OBJECT(thiswindow), "_dw_html_result_id", GINT_TO_POINTER(sigid+1)); | 9679 _set_signal_handler_id(object, sigid, cid); |
9638 return; | 9680 } |
9639 } | |
9640 #endif | |
9641 #if 0 | |
9642 else if (strcmp(signame, DW_SIGNAL_LOSE_FOCUS) == 0) | |
9643 { | |
9644 thisname = "focus-out-event"; | |
9645 if(GTK_IS_COMBO_BOX(thiswindow)) | |
9646 thiswindow = GTK_COMBO_BOX(thiswindow)->entry; | |
9647 } | |
9648 #endif | |
9649 else if (GTK_IS_SCALE(thiswindow) || GTK_IS_SCROLLBAR(thiswindow) || GTK_IS_SPIN_BUTTON(thiswindow) ) | |
9650 { | |
9651 thiswindow = (GtkWidget *)g_object_get_data(G_OBJECT(thiswindow), "_dw_adjustment"); | |
9652 } | |
9653 else if (GTK_IS_NOTEBOOK(thiswindow) && strcmp(signame, DW_SIGNAL_SWITCH_PAGE) == 0) | |
9654 { | |
9655 thisname = "switch-page"; | |
9656 } | |
9657 | |
9658 if (!thisfunc || !thiswindow) | |
9659 { | |
9660 free(params); | |
9661 return; | |
9662 } | |
9663 | |
9664 sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc, discfunc); | |
9665 params[0] = GINT_TO_POINTER(sigid); | |
9666 params[2] = (void *)thiswindow; | |
9667 cid = g_signal_connect_data(G_OBJECT(thiswindow), thisname, G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0); | |
9668 _set_signal_handler_id(thiswindow, sigid, cid); | |
9669 } | 9681 } |
9670 | 9682 |
9671 /* | 9683 /* |
9672 * Removes callbacks for a given window with given name. | 9684 * Removes callbacks for a given window with given name. |
9673 * Parameters: | 9685 * Parameters: |
9674 * window: Window handle of callback to be removed. | 9686 * window: Window handle of callback to be removed. |
9675 */ | 9687 */ |
9676 void dw_signal_disconnect_by_name(HWND window, const char *signame) | 9688 void dw_signal_disconnect_by_name(HWND window, const char *signame) |
9677 { | 9689 { |
9678 int z, count; | 9690 int z, count; |
9679 void *thisfunc; | 9691 SignalList *signal; |
9680 void **params = alloca(sizeof(void *) * 3); | 9692 void **params = alloca(sizeof(void *) * 3); |
9681 | 9693 |
9682 params[2] = _find_signal_window(window, signame); | 9694 params[2] = _find_signal_window(window, signame); |
9683 count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(params[2]), "_dw_sigcounter")); | 9695 count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(params[2]), "_dw_sigcounter")); |
9684 thisfunc = _findsigfunc(signame); | 9696 |
9685 | 9697 if((signal = _dw_findsignal(signame))) |
9686 for(z=0;z<count;z++) | 9698 { |
9687 { | 9699 for(z=0;z<count;z++) |
9688 SignalHandler sh; | 9700 { |
9689 | 9701 SignalHandler sh; |
9690 params[0] = GINT_TO_POINTER(z); | 9702 |
9691 sh = _get_signal_handler(params); | 9703 params[0] = GINT_TO_POINTER(z); |
9692 | 9704 sh = _get_signal_handler(params); |
9693 if(sh.intfunc == thisfunc) | 9705 |
9694 _remove_signal_handler((HWND)params[2], z); | 9706 if(sh.intfunc == signal->func) |
9707 _remove_signal_handler((HWND)params[2], z); | |
9708 } | |
9695 } | 9709 } |
9696 } | 9710 } |
9697 | 9711 |
9698 /* | 9712 /* |
9699 * Removes all callbacks for a given window. | 9713 * Removes all callbacks for a given window. |