comparison gtk4/dw.c @ 2273:95796965bb01

GTK4: More menu work, something still isn't working.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Mon, 01 Feb 2021 20:22:30 +0000
parents 2ce302c43f48
children b0bdd54bb2e8
comparison
equal deleted inserted replaced
2272:2ce302c43f48 2273:95796965bb01
1004 data = g_object_get_data(G_OBJECT(_DWApp), textbuf); 1004 data = g_object_get_data(G_OBJECT(_DWApp), textbuf);
1005 g_object_set_data(G_OBJECT(_DWApp), textbuf, NULL); 1005 g_object_set_data(G_OBJECT(_DWApp), textbuf, NULL);
1006 1006
1007 if(func) 1007 if(func)
1008 func((HWND)DW_ULONGLONG_TO_POINTER(g_variant_get_uint64(param)), data); 1008 func((HWND)DW_ULONGLONG_TO_POINTER(g_variant_get_uint64(param)), data);
1009 }
1010
1011 /* Handle menu click callbacks */
1012 static void _dw_menu_handler(GSimpleAction *action, GVariant *param, gpointer data)
1013 {
1014 SignalHandler work = _dw_get_signal_handler(data);
1015
1016 if(work.window)
1017 {
1018 int (*genericfunc)(HWND, void *) = work.func;
1019
1020 genericfunc(work.window, work.data);
1021 }
1009 } 1022 }
1010 1023
1011 static void _dw_app_activate(GApplication *app, gpointer user_data) 1024 static void _dw_app_activate(GApplication *app, gpointer user_data)
1012 { 1025 {
1013 /* Not sure why this signal is required, but GLib gives warnings 1026 /* Not sure why this signal is required, but GLib gives warnings
2216 } 2229 }
2217 *menu = NULL; 2230 *menu = NULL;
2218 } 2231 }
2219 } 2232 }
2220 2233
2221 char _dw_removetilde(char *dest, const char *src) 2234 char _dw_removetilde(char *action, char *dest, const char *src)
2222 { 2235 {
2223 int z, cur=0; 2236 int z, cur=0;
2224 char accel = '\0'; 2237 char accel = '\0';
2225 2238
2226 for(z=0;z<strlen(src);z++) 2239 for(z=0;z<strlen(src);z++)
2227 { 2240 {
2228 if(src[z] != '~') 2241 if(src[z] == '~')
2229 { 2242 {
2243 action[cur] = dest[cur] = '_';
2244 accel = src[z+1];
2245 }
2246 else if(src[z] == ' ')
2247 {
2248 action[cur] = '_';
2230 dest[cur] = src[z]; 2249 dest[cur] = src[z];
2231 cur++;
2232 } 2250 }
2233 else 2251 else
2234 { 2252 {
2235 dest[cur] = '_'; 2253 action[cur] = src[z];
2236 accel = src[z+1]; 2254 dest[cur] = src[z];
2237 cur++; 2255 }
2238 } 2256 cur++;
2239 } 2257 }
2240 dest[cur] = 0; 2258 dest[cur] = 0;
2241 return accel; 2259 return accel;
2242 } 2260 }
2243 2261
2253 * check: If TRUE menu is "check"able. 2271 * check: If TRUE menu is "check"able.
2254 * submenu: Handle to an existing menu to be a submenu or NULL. 2272 * submenu: Handle to an existing menu to be a submenu or NULL.
2255 */ 2273 */
2256 HWND dw_menu_append_item(HMENUI menu, const char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu) 2274 HWND dw_menu_append_item(HMENUI menu, const char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu)
2257 { 2275 {
2276 GSimpleAction *action = NULL;
2258 GMenuItem *tmphandle = NULL; 2277 GMenuItem *tmphandle = NULL;
2259 GMenuModel *menumodel; 2278 GMenuModel *menumodel;
2260 char accel, *temptitle = alloca(strlen(title)+1); 2279 char *temptitle = alloca(strlen(title)+1);
2280 char *tempaction = alloca(strlen(title)+1);
2261 int submenucount; 2281 int submenucount;
2262 2282
2263 if(!menu) 2283 if(!menu)
2264 return NULL; 2284 return 0;
2265 2285
2266 if(GTK_IS_POPOVER_MENU_BAR(menu)) 2286 if(GTK_IS_POPOVER_MENU_BAR(menu))
2267 menumodel = gtk_popover_menu_bar_get_menu_model(GTK_POPOVER_MENU_BAR(menu)); 2287 menumodel = gtk_popover_menu_bar_get_menu_model(GTK_POPOVER_MENU_BAR(menu));
2268 else 2288 else
2269 menumodel = gtk_popover_menu_get_menu_model(GTK_POPOVER_MENU(menu)); 2289 menumodel = gtk_popover_menu_get_menu_model(GTK_POPOVER_MENU(menu));
2270 accel = _dw_removetilde(temptitle, title); 2290 _dw_removetilde(tempaction, temptitle, title);
2271 submenucount = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "_dw_submenucount")); 2291 submenucount = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "_dw_submenucount"));
2272 2292
2273 if (strlen(temptitle) == 0) 2293 if (strlen(temptitle) == 0)
2274 tmphandle = g_menu_item_new_section(NULL, NULL); 2294 tmphandle = g_menu_item_new_section(NULL, NULL);
2275 else 2295 else
2276 { 2296 {
2277 char numbuf[25] = {0}; 2297 char tempbuf[101] = {0};
2278 2298
2279 if(submenu) 2299 if(submenu)
2280 { 2300 {
2281 char tempbuf[101] = {0};
2282 GMenuModel *submenumodel; 2301 GMenuModel *submenumodel;
2283 2302
2284 if(GTK_IS_POPOVER_MENU_BAR(submenu)) 2303 if(GTK_IS_POPOVER_MENU_BAR(submenu))
2285 submenumodel = gtk_popover_menu_bar_get_menu_model(GTK_POPOVER_MENU_BAR(submenu)); 2304 submenumodel = gtk_popover_menu_bar_get_menu_model(GTK_POPOVER_MENU_BAR(submenu));
2286 else 2305 else
2292 g_object_set_data(G_OBJECT(menu), tempbuf, (gpointer)submenu); 2311 g_object_set_data(G_OBJECT(menu), tempbuf, (gpointer)submenu);
2293 g_object_set_data(G_OBJECT(menu), "_dw_submenucount", GINT_TO_POINTER(submenucount)); 2312 g_object_set_data(G_OBJECT(menu), "_dw_submenucount", GINT_TO_POINTER(submenucount));
2294 } 2313 }
2295 else 2314 else
2296 { 2315 {
2297 tmphandle=g_menu_item_new(temptitle, NULL); 2316 char numbuf[25] = {0};
2317
2318 snprintf(tempbuf, 100, "menu.%s", tempaction);
2319 action = g_simple_action_new(tempbuf, NULL);
2320 g_object_ref(G_OBJECT(action));
2321 tmphandle=g_menu_item_new(temptitle, tempbuf);
2298 snprintf(numbuf, 24, "%lu", id); 2322 snprintf(numbuf, 24, "%lu", id);
2299 g_object_set_data(G_OBJECT(menu), numbuf, (gpointer)tmphandle); 2323 g_object_set_data(G_OBJECT(menu), numbuf, (gpointer)tmphandle);
2324 g_object_set_data(G_OBJECT(menu), "_dw_action", (gpointer)action);
2300 } 2325 }
2301 } 2326 }
2302 2327
2303 if(end) 2328 if(end)
2304 g_menu_append_item(G_MENU(menumodel), tmphandle); 2329 g_menu_append_item(G_MENU(menumodel), tmphandle);
2305 else 2330 else
2306 g_menu_prepend_item(G_MENU(menumodel), tmphandle); 2331 g_menu_prepend_item(G_MENU(menumodel), tmphandle);
2307 2332
2308 g_object_set_data(G_OBJECT(tmphandle), "_dw_id", GINT_TO_POINTER(id)); 2333 g_object_set_data(G_OBJECT(tmphandle), "_dw_id", GINT_TO_POINTER(id));
2309 2334
2310 /*if(flags & DW_MIS_DISABLED) 2335 if(action)
2311 gtk_widget_set_sensitive(tmphandle, FALSE);*/ 2336 g_simple_action_set_enabled(action, (flags & DW_MIS_DISABLED) ? FALSE : TRUE);
2312 return (HWND)tmphandle; 2337 return (HWND)tmphandle;
2313 } 2338 }
2314 2339
2315 GtkWidget *_find_submenu_id(GtkWidget *start, const char *name) 2340 GMenuItem *_dw_find_submenu_id(HMENUI start, const char *name)
2316 { 2341 {
2317 GtkWidget *tmp; 2342 GMenuItem *tmp;
2318 int z, submenucount = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(start), "_dw_submenucount")); 2343 int z, submenucount = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(start), "_dw_submenucount"));
2319 2344
2320 if((tmp = g_object_get_data(G_OBJECT(start), name))) 2345 if((tmp = g_object_get_data(G_OBJECT(start), name)))
2321 return tmp; 2346 return tmp;
2322 2347
2323 for(z=0;z<submenucount;z++) 2348 for(z=0;z<submenucount;z++)
2324 { 2349 {
2325 char tempbuf[101] = {0}; 2350 char tempbuf[101] = {0};
2326 GtkWidget *submenu, *menuitem; 2351 GMenuItem *menuitem;
2352 HMENUI submenu;
2327 2353
2328 snprintf(tempbuf, 100, "_dw_submenu%d", z); 2354 snprintf(tempbuf, 100, "_dw_submenu%d", z);
2329 2355
2330 if((submenu = g_object_get_data(G_OBJECT(start), tempbuf))) 2356 if((submenu = g_object_get_data(G_OBJECT(start), tempbuf)))
2331 { 2357 {
2332 if((menuitem = _find_submenu_id(submenu, name))) 2358 if((menuitem = _dw_find_submenu_id(submenu, name)))
2333 return menuitem; 2359 return menuitem;
2334 } 2360 }
2335 } 2361 }
2336 return NULL; 2362 return NULL;
2337 } 2363 }
2344 * check: TRUE for checked FALSE for not checked. 2370 * check: TRUE for checked FALSE for not checked.
2345 * deprecated: use dw_menu_item_set_state() 2371 * deprecated: use dw_menu_item_set_state()
2346 */ 2372 */
2347 void dw_menu_item_set_check(HMENUI menu, unsigned long id, int check) 2373 void dw_menu_item_set_check(HMENUI menu, unsigned long id, int check)
2348 { 2374 {
2349 #if 0 /* TODO: Implement this with GMenuModel and GtkPopoverMenu */ 2375 #if 0
2350 char numbuf[25] = {0}; 2376 char numbuf[25] = {0};
2351 GtkWidget *tmphandle; 2377 GMenuItem *tmphandle;
2352 2378
2353 if(!menu) 2379 if(!menu)
2354 return; 2380 return;
2355 2381
2356 snprintf(numbuf, 24, "%lu", id); 2382 snprintf(numbuf, 24, "%lu", id);
2357 tmphandle = _find_submenu_id(menu, numbuf); 2383 tmphandle = _dw_find_submenu_id(menu, numbuf);
2358 2384
2359 if(tmphandle) 2385 if(tmphandle && G_IS_MENU_ITEM(tmphandle))
2360 { 2386 {
2361 _dw_ignore_click = 1; 2387 GSimpleAction *action = g_object_get_data(G_OBJECT(tmphandle), "_dw_action");
2388
2362 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(tmphandle)) != check) 2389 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(tmphandle)) != check)
2363 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check); 2390 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check);
2364 _dw_ignore_click = 0;
2365 } 2391 }
2366 #endif 2392 #endif
2367 } 2393 }
2368 2394
2369 /* 2395 /*
2373 * id: Menuitem id. 2399 * id: Menuitem id.
2374 * state: TRUE for checked FALSE for not checked. 2400 * state: TRUE for checked FALSE for not checked.
2375 */ 2401 */
2376 void dw_menu_item_set_state(HMENUI menu, unsigned long id, unsigned long state) 2402 void dw_menu_item_set_state(HMENUI menu, unsigned long id, unsigned long state)
2377 { 2403 {
2378 #if 0 /* TODO: Implement this with GMenuModel and GtkPopoverMenu */
2379 char numbuf[25] = {0}; 2404 char numbuf[25] = {0};
2380 GtkWidget *tmphandle; 2405 GMenuItem *tmphandle;
2381 int check;
2382 2406
2383 if(!menu) 2407 if(!menu)
2384 return; 2408 return;
2385 2409
2386 snprintf(numbuf, 24, "%lu", id); 2410 snprintf(numbuf, 24, "%lu", id);
2387 tmphandle = _find_submenu_id(menu, numbuf); 2411 tmphandle = _dw_find_submenu_id(menu, numbuf);
2388 2412
2389 if ( (state & DW_MIS_CHECKED) || (state & DW_MIS_UNCHECKED) ) 2413 if(tmphandle && G_IS_MENU_ITEM(tmphandle))
2390 { 2414 {
2391 if ( state & DW_MIS_CHECKED ) 2415 GSimpleAction *action = g_object_get_data(G_OBJECT(tmphandle), "_dw_action");
2392 check = 1; 2416
2393 else 2417 #if 0
2394 check = 0; 2418 if((state & DW_MIS_CHECKED) || (state & DW_MIS_UNCHECKED))
2395 2419 {
2396 if (tmphandle) 2420 int check = 0;
2397 { 2421
2398 _dw_ignore_click = 1; 2422 if(state & DW_MIS_CHECKED)
2423 check = 1;
2424
2399 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(tmphandle)) != check) 2425 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(tmphandle)) != check)
2400 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check); 2426 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check);
2401 _dw_ignore_click = 0; 2427 }
2402 } 2428 #endif
2403 } 2429 if((state & DW_MIS_ENABLED) || (state & DW_MIS_DISABLED))
2404 if ( (state & DW_MIS_ENABLED) || (state & DW_MIS_DISABLED) ) 2430 {
2405 { 2431 if(state & DW_MIS_ENABLED)
2406 if (tmphandle ) 2432 g_simple_action_set_enabled(action, TRUE);
2407 {
2408 _dw_ignore_click = 1;
2409 if ( state & DW_MIS_ENABLED )
2410 gtk_widget_set_sensitive( tmphandle, TRUE );
2411 else 2433 else
2412 gtk_widget_set_sensitive( tmphandle, FALSE ); 2434 g_simple_action_set_enabled(action, FALSE);
2413 _dw_ignore_click = 0; 2435 }
2414 } 2436 }
2415 }
2416 #endif
2417 } 2437 }
2418 2438
2419 /* 2439 /*
2420 * Deletes the menu item specified. 2440 * Deletes the menu item specified.
2421 * Parameters: 2441 * Parameters:
2425 * DW_ERROR_NONE (0) on success or DW_ERROR_UNKNOWN on failure. 2445 * DW_ERROR_NONE (0) on success or DW_ERROR_UNKNOWN on failure.
2426 */ 2446 */
2427 int API dw_menu_delete_item(HMENUI menu, unsigned long id) 2447 int API dw_menu_delete_item(HMENUI menu, unsigned long id)
2428 { 2448 {
2429 int ret = DW_ERROR_UNKNOWN; 2449 int ret = DW_ERROR_UNKNOWN;
2430 #if 0 /* TODO: Implement this with GMenuModel and GtkPopoverMenu */
2431 char numbuf[25] = {0}; 2450 char numbuf[25] = {0};
2432 GtkWidget *tmphandle; 2451 GMenuItem *tmphandle;
2433 2452
2434 if(!menu) 2453 if(!menu)
2435 return ret; 2454 return ret;
2436 2455
2437 snprintf(numbuf, 24, "%lu", id); 2456 snprintf(numbuf, 24, "%lu", id);
2438 tmphandle = _find_submenu_id(menu, numbuf); 2457 tmphandle = _dw_find_submenu_id(menu, numbuf);
2439 2458
2440 if(tmphandle) 2459 if(tmphandle && G_IS_MENU_ITEM(tmphandle))
2441 { 2460 {
2442 if(GTK_IS_WIDGET(tmphandle)) 2461 /* g_menu_remove(menu, position); */
2443 g_object_unref(G_OBJECT(tmphandle)); 2462 g_object_unref(G_OBJECT(tmphandle));
2444 g_object_set_data(G_OBJECT(menu), numbuf, NULL); 2463 g_object_set_data(G_OBJECT(menu), numbuf, NULL);
2445 ret = DW_ERROR_NONE; 2464 ret = DW_ERROR_NONE;
2446 } 2465 }
2447 #endif
2448 return ret; 2466 return ret;
2449 } 2467 }
2450 2468
2451 /* 2469 /*
2452 * Pops up a context menu at given x and y coordinates. 2470 * Pops up a context menu at given x and y coordinates.
2456 * x: X coordinate. 2474 * x: X coordinate.
2457 * y: Y coordinate. 2475 * y: Y coordinate.
2458 */ 2476 */
2459 void dw_menu_popup(HMENUI *menu, HWND parent, int x, int y) 2477 void dw_menu_popup(HMENUI *menu, HWND parent, int x, int y)
2460 { 2478 {
2461 if(!menu || !*menu) 2479 if(menu && *menu && GTK_IS_WIDGET(*menu))
2462 return; 2480 {
2463 2481 GtkWidget *popover = gtk_popover_new();
2464 #if 0 /* TODO: Implement this with GMenuModel and GtkPopoverMenu */ 2482
2465 popup = parent; 2483 gtk_popover_set_child(GTK_POPOVER(popover), GTK_WIDGET(*menu));
2466 2484 gtk_popover_set_offset(GTK_POPOVER(popover), x, y);
2467 gtk_menu_popup_at_pointer(GTK_MENU(*menu), NULL); 2485 gtk_popover_set_autohide(GTK_POPOVER(popover), TRUE);
2468 #endif 2486 gtk_popover_popup(GTK_POPOVER(popover));
2469 *menu = NULL; 2487 *menu = NULL;
2488 }
2470 } 2489 }
2471 2490
2472 2491
2473 /* 2492 /*
2474 * Returns the current X and Y coordinates of the mouse pointer. 2493 * Returns the current X and Y coordinates of the mouse pointer.
9519 return NULL; 9538 return NULL;
9520 } 9539 }
9521 /* GTK signal name for check buttons is "toggled" not "clicked" */ 9540 /* GTK signal name for check buttons is "toggled" not "clicked" */
9522 else if(GTK_IS_CHECK_BUTTON(object) && strcmp(signal->name, DW_SIGNAL_CLICKED) == 0) 9541 else if(GTK_IS_CHECK_BUTTON(object) && strcmp(signal->name, DW_SIGNAL_CLICKED) == 0)
9523 strcpy(signal->gname, "toggled"); 9542 strcpy(signal->gname, "toggled");
9543 /* For menu items, get the G(Simple)Action and the signal is "activate" */
9544 else if(G_IS_MENU_ITEM(object) && strcmp(signal->name, DW_SIGNAL_CLICKED) == 0)
9545 {
9546 GSimpleAction *action = G_SIMPLE_ACTION(g_object_get_data(object, "_dw_action"));
9547
9548 if(action)
9549 {
9550 int cid, sigid = _dw_set_signal_handler(G_OBJECT(action), (HWND)object, sigfunc, data, (gpointer)_dw_menu_handler, discfunc);
9551
9552 params[0] = DW_INT_TO_POINTER(sigid);
9553 params[2] = DW_POINTER(object);
9554 cid = g_signal_connect_data(G_OBJECT(action), "activate", G_CALLBACK(_dw_menu_handler), params, _dw_signal_disconnect, 0);
9555 _dw_set_signal_handler_id(object, sigid, cid);
9556 }
9557 return NULL;
9558 }
9524 return object; 9559 return object;
9525 } 9560 }
9526 9561
9527 GObject *_dw_mouse_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data) 9562 GObject *_dw_mouse_setup(struct _dw_signal_list *signal, GObject *object, void *params[], void *sigfunc, void *discfunc, void *data)
9528 { 9563 {