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.