diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index d57d265..9a4d5d1 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -19,18 +19,19 @@ jobs: - linux/arm/v6 - linux/arm/v7 - linux/arm64 + gtk4: [ON, OFF] steps: - uses: actions/checkout@v4 - name: dependencies - run: sudo apt install --fix-missing cmake gcc gfortran libx11-dev libglu1-mesa-dev libmotif-dev tcsh libxaw7-dev libglew-dev libdlm-dev libgl2ps-dev libpng-dev + run: sudo apt install --fix-missing cmake gcc gfortran libx11-dev libglu1-mesa-dev libmotif-dev tcsh libxaw7-dev libglew-dev libdlm-dev libgl2ps-dev libpng-dev libgtk-4-dev - name: clean run: make clean - name: configure - run: make config + run: make config OPENPHIGS_OPTS="-DUSE_GTK4=${{ matrix.gtk4 }}" - name: Build run: make build diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e89368f..b3a8519 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,11 +7,21 @@ FIND_PACKAGE(PNG REQUIRED) FIND_PACKAGE(OpenGL REQUIRED) FIND_PACKAGE(X11 REQUIRED) FIND_PACKAGE(XMU REQUIRED) -FIND_PACKAGE(Motif REQUIRED) +FIND_PACKAGE(Motif) FIND_PACKAGE(GLEW) FIND_PACKAGE(epoxy) FIND_LIBRARY(MATH_LIBRARY m) +option(USE_GTK4 "Use GTK4 for widgets instead of Motif/Xaw" OFF) +if (USE_GTK4) + FIND_PACKAGE(PkgConfig REQUIRED) + pkg_check_modules(GTK4 REQUIRED gtk4) +else() + if(NOT Motif_FOUND) + message(FATAL_ERROR "Motif not found but USE_GTK4 is OFF. You must have Motif installed.") + endif() +endif() + if (APPLE) set(CMAKE_C_COMPILER gcc) set(CMAKE_C_COMPILER_ID GNU) @@ -50,8 +60,12 @@ add_definitions(-g) # add_definitions(-DDEBUGINP) #add_definitions(-DDEBUGCL) # -# use Motif widgets rather than Xaw -add_definitions(-DMOTIF) +# use Motif or GTK4 widgets rather than Xaw +if(USE_GTK4) + add_definitions(-DGTK4_EXT) +else() + add_definitions(-DMOTIF) +endif() # use GLEW or epoxy if (USE_GLEW) @@ -65,15 +79,23 @@ endif() # gl2ps FIND_PATH(GL2PS_INCLUDE_DIR gl2ps.h) FIND_LIBRARY(GL2PS_LIBRARY NAMES gl2ps) -add_definitions(-DGLEW) -set (GL_INCLUDES ${GL2PS_INCLUDE_DIR}) +if (GL2PS_INCLUDE_DIR) + list(APPEND GL_INCLUDES ${GL2PS_INCLUDE_DIR}) +endif() message(STATUS "GL Includes=${GL_INCLUDES}") -include_directories(${X11_INCLUDE_DIR} ${MOTIF_INCLUDE_DIR} ${GL_INCLUDES}) +if (USE_GTK4) + include_directories(${X11_INCLUDE_DIR} ${GTK4_INCLUDE_DIRS} ${GL_INCLUDES}) + SET(CMAKE_C_FLAGS "$ENV{CFLAGS} -DGTK4_EXT -g -O0 -fPIC -Wno-deprecated-non-prototype") + SET(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -DGTK4_EXT -g -O0 -fPIC -Wno-deprecated-non-prototype") + SET(CMAKE_Fortran_FLAGS "$ENV{FFLAGS} -DGTK4_EXT -finit-local-zero -g -O0 -fPIC") +else() + include_directories(${X11_INCLUDE_DIR} ${MOTIF_INCLUDE_DIR} ${GL_INCLUDES}) + SET(CMAKE_C_FLAGS "$ENV{CFLAGS} -DMOTIF -g -O0 -fPIC -Wno-deprecated-non-prototype") + SET(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -DMOTIF -g -O0 -fPIC -Wno-deprecated-non-prototype") + SET(CMAKE_Fortran_FLAGS "$ENV{FFLAGS} -DMOTIF -finit-local-zero -g -O0 -fPIC") +endif() -SET(CMAKE_C_FLAGS "$ENV{CFLAGS} -DMOTIF -g -O0 -fPIC -Wno-deprecated-non-prototype") -SET(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -DMOTIF -g -O0 -fPIC -Wno-deprecated-non-prototype") -SET(CMAKE_Fortran_FLAGS "$ENV{FFLAGS} -DMOTIF -finit-local-zero -g -O0 -fPIC") SET(CMAKE_EXE_LINKER_FLAGS $ENV{LDFLAGS}) if (OPENPHIGS_FORCE_32) @@ -98,11 +120,17 @@ INCLUDE_DIRECTORIES( set (XLIBS "") endif() +if (USE_GTK4) + set(UI_LIBRARIES ${GTK4_LIBRARIES}) +else() + set(UI_LIBRARIES ${MOTIF_LIBRARIES}) +endif() + if (USE_GLEW) SET(PHIGS_LIBRARIES phigs ${XLIBS} - ${MOTIF_LIBRARIES} + ${UI_LIBRARIES} ${XMU_LIBRARY} ${PNG_LIBRARY} ${X11_Xaw_LIB} @@ -117,7 +145,7 @@ else() SET(PHIGS_LIBRARIES phigs ${XLIBS} - ${MOTIF_LIBRARIES} + ${UI_LIBRARIES} ${XMU_LIBRARY} ${PNG_LIBRARY} ${X11_Xaw_LIB} diff --git a/src/include/phigs/private/wsglP.h b/src/include/phigs/private/wsglP.h index d5d6266..b57e85b 100644 --- a/src/include/phigs/private/wsglP.h +++ b/src/include/phigs/private/wsglP.h @@ -197,6 +197,17 @@ extern "C" { */ void wsgl_clear_geometry(); + /******************************************************************************* + /******************************************************************************* + * wsgl_set_transparency_pass + * + * DESCR: Set the transparency pass and update HLHSR depth mask. + * RETURNS: N/A + */ + void wsgl_set_transparency_pass(Ws *ws, int pass); + + extern int wsgl_current_transparency_pass; + /******************************************************************************* * wsgl_init * diff --git a/src/include/phigs/sin.h b/src/include/phigs/sin.h index 89fb1a3..49f4b5d 100644 --- a/src/include/phigs/sin.h +++ b/src/include/phigs/sin.h @@ -51,7 +51,22 @@ SOFTWARE. #include #include +#ifdef GTK4_EXT +#include +#ifndef OPENPHIGS_GTK4_TYPES_DEFINED +#define OPENPHIGS_GTK4_TYPES_DEFINED +typedef void* XtAppContext; +typedef GtkWidget* Widget; +typedef void* XtPointer; +typedef unsigned int Cardinal; +typedef char* String; +typedef void* Arg; +typedef void* ArgList; +typedef unsigned long XtArgVal; +#endif +#else #include +#endif #include "phigs.h" #include "ws_type.h" @@ -391,8 +406,10 @@ extern void phg_sin_sample(); */ /* Xt action procs for input. */ +#ifndef GTK4_EXT extern XtActionProc phg_sin_xt_request_satisfied(Widget); extern XtActionProc phg_sin_xt_string_event(Widget, XEvent*, String *, Cardinal*); +#endif #define SIN_CLASS_INDEX(_class) \ ((int)(_class)) diff --git a/src/include/phigs/ws.h b/src/include/phigs/ws.h index caf84ca..737e26e 100644 --- a/src/include/phigs/ws.h +++ b/src/include/phigs/ws.h @@ -51,7 +51,22 @@ SOFTWARE. #include #include +#ifdef GTK4_EXT +#include +#ifndef OPENPHIGS_GTK4_TYPES_DEFINED +#define OPENPHIGS_GTK4_TYPES_DEFINED +typedef void* XtAppContext; +typedef GtkWidget* Widget; +typedef void* XtPointer; +typedef unsigned int Cardinal; +typedef char* String; +typedef void* Arg; +typedef void* ArgList; +typedef unsigned long XtArgVal; +#endif +#else #include +#endif #include #include "phigs.h" diff --git a/src/libphigs/cp/cpm_tlkt.c b/src/libphigs/cp/cpm_tlkt.c index fcfc60a..b21c19d 100644 --- a/src/libphigs/cp/cpm_tlkt.c +++ b/src/libphigs/cp/cpm_tlkt.c @@ -48,12 +48,17 @@ SOFTWARE. ******************************************************************/ #include +#ifndef GTK4_EXT #include +#ifndef GTK4_EXT #include +#endif +#endif #include "phg.h" #include "ws.h" #include "sin.h" +#ifndef GTK4_EXT /* TODO: Fill in the real options. */ static XrmOptionDescRec options[] = { {"-horiz", "scrollbar.orientation", XrmoptionNoArg, "horizontal"} @@ -300,6 +305,7 @@ static XtActionsRec actions[] = { }; XContext phg_sin_device_context_id; +#endif /* No need for a "destroy_toolkit function since all the resources are * destroyed when the PM terminates. @@ -307,8 +313,11 @@ XContext phg_sin_device_context_id; XtAppContext phg_cpm_init_toolkit( int argc, char **argv ) { - XtAppContext app_con; + XtAppContext app_con = NULL; +#ifdef GTK4_EXT + gtk_init(); +#else XtToolkitInitialize(); #ifdef DEBUGINP printf("Initialising Xt Toolkit\n"); @@ -321,6 +330,7 @@ XtAppContext phg_cpm_init_toolkit( int argc, char **argv ) XtAppAddActions( app_con, actions, XtNumber(actions) ); phg_sin_device_context_id = XUniqueContext(); } +#endif return app_con; } @@ -328,13 +338,20 @@ Widget phg_cpm_toolkit_add_connection( XtAppContext context, Display* display, P { int argc = 0, status = 0; char **argv = (char **)NULL; - Widget top_level; + Widget top_level = NULL; + *err = 0; +#ifdef GTK4_EXT + /* In GTK4, Display connection is handled by gtk_init() or implicitly. */ + /* We can create a dummy or invisible top-level window if needed, but + * OpenPHIGS handles GLX on X11 windows directly. We just need to return + * a valid pointer to indicate success if the caller checks it. */ + top_level = (Widget)gtk_window_new(); +#else /* TODO: XtDisplayInitialize destroys the arg vector, but we need to * keep it for the next display initialized. So copy it to scratch * space then pass the copy. */ - *err = 0; XtDisplayInitialize( context, display, "Workstation", NULL, NULL, 0, &argc, argv ); @@ -342,6 +359,7 @@ Widget phg_cpm_toolkit_add_connection( XtAppContext context, Display* display, P display, NULL ); if (top_level == NULL) *err = ERRN204; +#endif return top_level; } @@ -354,16 +372,30 @@ int phg_cpm_toolkit_open_ws( Ws *ws ) { #endif status = 0; sprintf( buf, "workstation%d", ws->id ); +#ifdef GTK4_EXT + ws->shell = (Widget)gtk_window_new(); + if (ws->shell == NULL){ + status = 1; + } +#else ws->shell = XtVaCreatePopupShell( buf, applicationShellWidgetClass, ws->top_level, NULL); if (ws->shell == NULL){ printf("Failed to create shell for %s! Top_level was %ld\n", buf, (long)ws->top_level); status = 1; } +#endif return status; } void phg_cpm_toolkit_close_ws( Ws *ws ) { +#ifdef GTK4_EXT + if (ws->shell) { + gtk_window_destroy(GTK_WINDOW(ws->shell)); + ws->shell = NULL; + } +#else XtDestroyWidget( ws->shell ); +#endif } diff --git a/src/libphigs/input/sin_cho.c b/src/libphigs/input/sin_cho.c index 856f549..d95fea1 100644 --- a/src/libphigs/input/sin_cho.c +++ b/src/libphigs/input/sin_cho.c @@ -59,17 +59,21 @@ SOFTWARE. #include "sin.h" #include "private/sinP.h" +#ifndef GTK4_EXT #include #include +#endif #ifdef MOTIF #include #include #include #include #else +#ifndef GTK4_EXT #include #include #endif +#endif /******************************************************************************* * choice_notify * @@ -167,7 +171,19 @@ static void enable_choice( sprintf( buf, "choice%d", device->num ); sprintf( title, "Options:"); /* Create the containing shell. */ -#ifdef MOTIF +#ifdef GTK4_EXT + if (device->item_handle.choice.shell) { + gtk_window_destroy(GTK_WINDOW(device->item_handle.choice.shell)); + device->item_handle.choice.shell = NULL; + } + device->item_handle.choice.shell = (Widget)gtk_window_new(); + gtk_window_set_title(GTK_WINDOW(device->item_handle.choice.shell), title); + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + gtk_window_set_child(GTK_WINDOW(device->item_handle.choice.shell), box); + device->item_handle.choice.list = (Widget)gtk_list_box_new(); + gtk_box_append(GTK_BOX(box), (GtkWidget*)device->item_handle.choice.list); + w = device->item_handle.choice.list; +#elif defined(MOTIF) device->item_handle.choice.shell = XtVaCreatePopupShell( buf, applicationShellWidgetClass, parent, @@ -230,10 +246,14 @@ static void enable_choice( XtNcallback, choice_notify, (XtPointer)device ); #endif +#ifdef GTK4_EXT + gtk_window_present(GTK_WINDOW(device->item_handle.choice.shell)); +#else XtPopup( device->item_handle.choice.shell, XtGrabNone ); if ( device->mode == SIN_REQUEST_PENDING ) XSaveContext( XtDisplay(w), XtWindow(w), phg_sin_device_context_id, (caddr_t)device ); +#endif #ifdef DEBUGINP printf("Enabling choice finished\n"); #endif diff --git a/src/libphigs/input/sin_str.c b/src/libphigs/input/sin_str.c index 983fdc1..6f41c1b 100644 --- a/src/libphigs/input/sin_str.c +++ b/src/libphigs/input/sin_str.c @@ -59,15 +59,19 @@ SOFTWARE. #include "sin.h" #include "private/sinP.h" +#ifndef GTK4_EXT #include #include +#endif #ifdef MOTIF #include #include #else +#ifndef GTK4_EXT #include #include #endif +#endif /******************************************************************************* * reset_string_measure @@ -75,7 +79,13 @@ SOFTWARE. * DESCR: Reset string measure helper function * RETURNS: N/A */ -#ifdef MOTIF +#ifdef GTK4_EXT +static void reset_string_measure(Sin_input_device *device) { + if (device->item_handle.string.textw) { + gtk_editable_set_text(GTK_EDITABLE(device->item_handle.string.textw), device->data.string.init_string ? device->data.string.init_string : ""); + } +} +#elif defined(MOTIF) static void reset_string_measure( Sin_input_device *device ) @@ -127,7 +137,16 @@ static void reset_string_measure( * RETURNS: N/A */ -#ifdef MOTIF +#ifdef GTK4_EXT +static void update_string(Sin_input_device *device) { + Sin_string_device_data *data = &device->data.string; + if (device->item_handle.string.textw) { + const char *text = gtk_editable_get_text(GTK_EDITABLE(device->item_handle.string.textw)); + strncpy(data->string, text, data->buffer_size - 1); + data->string[data->buffer_size - 1] = '\0'; + } +} +#elif defined(MOTIF) static void update_string( Sin_input_device *device ) @@ -183,6 +202,7 @@ static void update_string( * RETURNS: N/A */ +#ifndef GTK4_EXT XtActionProc phg_sin_xt_string_event( Widget w, XEvent *event, @@ -210,11 +230,14 @@ XtActionProc phg_sin_xt_string_event( } return NULL; } +#endif +#ifndef GTK4_EXT static XtTranslations compiled_translations; static String translations = "\ Return: newline() StringEvent() RequestSatisfied() \n\ "; +#endif /******************************************************************************* * create_string @@ -239,7 +262,15 @@ static void create_string( #endif /* Create the containing shell. */ sprintf( buf, "string%d", device->num ); -#ifdef MOTIF +#ifdef GTK4_EXT + widgets->shell = (Widget)gtk_window_new(); + gtk_window_set_title(GTK_WINDOW(widgets->shell), "String Input"); + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + gtk_window_set_child(GTK_WINDOW(widgets->shell), box); + widgets->textw = (Widget)gtk_entry_new(); + gtk_box_append(GTK_BOX(box), (GtkWidget*)widgets->textw); + widgets->pane = (Widget)box; +#elif defined(MOTIF) widgets->shell = XtVaCreatePopupShell( buf, applicationShellWidgetClass, parent, @@ -281,10 +312,12 @@ static void create_string( NULL ); #endif +#ifndef GTK4_EXT if ( !compiled_translations ) { compiled_translations = XtParseTranslationTable( translations ); } XtOverrideTranslations( widgets->textw, compiled_translations ); +#endif #ifdef DEBUGINP printf("Done with create string.\n"); #endif @@ -309,14 +342,20 @@ static void enable_string( create_string( device ); reset_string_measure( device ); +#ifdef GTK4_EXT + gtk_window_present(GTK_WINDOW(device->item_handle.string.shell)); +#else XtPopup( device->item_handle.string.shell, XtGrabNone ); +#endif if ( !device->flags.been_up_yet ) { #ifdef DEBUGINP printf("Setting flags\n"); #endif +#ifndef GTK4_EXT XSaveContext( XtDisplay(device->item_handle.string.textw), XtWindow(device->item_handle.string.textw), phg_sin_device_context_id, (caddr_t)device ); +#endif device->flags.been_up_yet = 1; } #ifdef DEBUGINP @@ -357,8 +396,13 @@ static void disable_string( #ifdef DEBUGINP printf("Disable string.\n"); #endif - if ( device->item_handle.string.shell ) + if ( device->item_handle.string.shell ) { +#ifdef GTK4_EXT + gtk_window_close(GTK_WINDOW(device->item_handle.string.shell)); +#else XtPopdown( device->item_handle.string.shell ); +#endif + } } /******************************************************************************* @@ -375,8 +419,13 @@ static void destroy_string( #ifdef DEBUGINP printf("Destroy string.\n"); #endif - if ( device->item_handle.string.shell ) + if ( device->item_handle.string.shell ) { +#ifdef GTK4_EXT + gtk_window_destroy(GTK_WINDOW(device->item_handle.string.shell)); +#else XtDestroyWidget( device->item_handle.string.shell ); +#endif + } } /******************************************************************************* diff --git a/src/libphigs/input/sin_val.c b/src/libphigs/input/sin_val.c index 8719f11..dc97304 100644 --- a/src/libphigs/input/sin_val.c +++ b/src/libphigs/input/sin_val.c @@ -59,8 +59,10 @@ SOFTWARE. #include "sin.h" #include "private/sinP.h" +#ifndef GTK4_EXT #include #include +#endif #ifdef MOTIF #include #include @@ -68,11 +70,13 @@ SOFTWARE. #include #include #else +#ifndef GTK4_EXT #include #include #include #include #endif +#endif /******************************************************************************* * init_valuator * @@ -139,7 +143,9 @@ static void valuator_jump( float delta, prec; Sin_input_device *device = (Sin_input_device *)client_data; Sin_valuator_device_data *data = &device->data.valuator; -#ifdef MOTIF +#ifdef GTK4_EXT + data->value = gtk_range_get_value(GTK_RANGE(device->item_handle.valuator.scrollbar)); +#elif defined(MOTIF) XmScaleCallbackStruct *cbs = (XmScaleCallbackStruct *) call_data; delta = data->high - data->low; if (delta<=1.0) prec = 100.0; @@ -220,7 +226,30 @@ static void enable_valuator( if (device->item_handle.valuator.pane != NULL){ return; } -#ifdef MOTIF +#ifdef GTK4_EXT + if (device->item_handle.valuator.shell == NULL) { + ws->valuator_shell = (Widget)gtk_window_new(); + gtk_window_set_title(GTK_WINDOW(ws->valuator_shell), "Valuator"); + + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + gtk_window_set_child(GTK_WINDOW(ws->valuator_shell), box); + ws->valuator_box = (Widget)box; + + if (data->label) { + GtkWidget *lbl = gtk_label_new(data->label); + gtk_box_append(GTK_BOX(box), lbl); + } + + device->item_handle.valuator.scrollbar = (Widget)gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, data->low, data->high, (data->high - data->low)/100.0); + gtk_range_set_value(GTK_RANGE(device->item_handle.valuator.scrollbar), data->init_value); + g_signal_connect(device->item_handle.valuator.scrollbar, "value-changed", G_CALLBACK(valuator_jump), device); + gtk_box_append(GTK_BOX(box), (GtkWidget*)device->item_handle.valuator.scrollbar); + + gtk_window_present(GTK_WINDOW(ws->valuator_shell)); + } + device->item_handle.valuator.shell = ws->valuator_shell; + device->item_handle.valuator.pane = ws->valuator_box; +#elif defined(MOTIF) XmString label; /* Create the containing shell. */ sprintf( buf, "valuator%d", device->num ); diff --git a/src/libphigs/input/sin_ws.c b/src/libphigs/input/sin_ws.c index f879e5e..2c2ffea 100644 --- a/src/libphigs/input/sin_ws.c +++ b/src/libphigs/input/sin_ws.c @@ -613,6 +613,7 @@ void phg_sin_ws_flush_event_buffer( SIN_WS_RESET_EVENT_BUFFER(ev_buf); } +#ifndef GTK4_EXT XtActionProc phg_sin_xt_request_satisfied( Widget w ) @@ -625,3 +626,4 @@ XtActionProc phg_sin_xt_request_satisfied( } return NULL; } +#endif diff --git a/src/libphigs/ws/ws_inp.c b/src/libphigs/ws/ws_inp.c index 83aae05..61d7cff 100644 --- a/src/libphigs/ws/ws_inp.c +++ b/src/libphigs/ws/ws_inp.c @@ -50,8 +50,10 @@ SOFTWARE. #include #include #include +#ifndef GTK4_EXT #include #include +#endif #include "phg.h" #include "ws.h" diff --git a/src/libphigs/ws/ws_pm.c b/src/libphigs/ws/ws_pm.c index 28f1b8d..fc1859e 100644 --- a/src/libphigs/ws/ws_pm.c +++ b/src/libphigs/ws/ws_pm.c @@ -57,47 +57,67 @@ SOFTWARE. #include "cp.h" #include "ws.h" #include "private/wsxP.h" +#ifndef GTK4_EXT #include #include #include +#endif #ifdef MOTIF #include #include #include #include #else +#ifndef GTK4_EXT #include #include #include #endif +#endif int done_pressed = 0; +#ifdef GTK4_EXT +static void done_button( GtkWidget *w, gpointer data ) +{ + Ws *ws = (Ws *)data; + done_pressed = 1; + gtk_window_destroy(GTK_WINDOW(ws->msg_shell)); + ws->msg_shell = NULL; +} +#else void done_button( Widget w, XtPointer client_data, XtPointer call_data ) { Ws *ws = (Ws *)client_data; -#ifdef DEBUGINP - printf("Done button pressed\n"); -#endif done_pressed = 1; XtPopdown( ws->msg_shell ); } +#endif void create_message_win( Ws *ws ) { +#ifdef GTK4_EXT + ws->msg_shell = (Widget)gtk_window_new(); + gtk_window_set_title(GTK_WINDOW(ws->msg_shell), "Message"); + gtk_window_set_default_size(GTK_WINDOW(ws->msg_shell), 400, 100); + + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + gtk_window_set_child(GTK_WINDOW(ws->msg_shell), box); + + ws->msg_label = (Widget)gtk_label_new(""); + gtk_box_append(GTK_BOX(box), (GtkWidget*)ws->msg_label); + + GtkWidget *button = gtk_button_new_with_label("OK"); + g_signal_connect(button, "clicked", G_CALLBACK(done_button), ws); + gtk_box_append(GTK_BOX(box), button); +#else Widget frame, pane, box, text, button; -#ifdef DEBUGINP - printf("Creating message window\n"); -#endif /* Create the containing shell. */ ws->msg_shell = XtVaCreatePopupShell( "message", applicationShellWidgetClass, ws->top_level, NULL ); -#ifdef DEBUGINP - printf("Called XtVaCreatePopupShell. msg_shell is %ld\n", (long)ws->msg_shell); -#endif #ifdef MOTIF frame = XtVaCreateManagedWidget( "frame", xmFrameWidgetClass, ws->msg_shell, @@ -129,6 +149,7 @@ void create_message_win( Ws *ws ) ws->msg_label = XtVaCreateManagedWidget( "label", labelWidgetClass, box, NULL ); #endif +#endif } void phg_wsb_message( @@ -146,12 +167,13 @@ void phg_wsb_message( } if ( args->msg_length > 0 ) { +#ifdef GTK4_EXT + gtk_label_set_text(GTK_LABEL(ws->msg_label), args->msg); + gtk_window_present(GTK_WINDOW(ws->msg_shell)); +#else /* The unmanage and manage is to get the parent box to allow the * label resize. */ -#ifdef DEBUGINP - printf("Setting message window parameters. Message is %s\n", args->msg); -#endif XtUnmanageChild( ws->msg_label ); #ifdef MOTIF XmString btext = XmStringCreateSimple(args->msg); @@ -165,15 +187,16 @@ void phg_wsb_message( #endif XtManageChild( ws->msg_label ); XtPopup( ws->msg_shell, XtGrabNone ); -#ifdef DEBUGINP - printf("Popup done.\n"); #endif } phg_wsx_update_ws_rect( ws ); -#ifdef DEBUGINP - printf("DEBUG: ws_pm: entering main loop\n"); -#endif + done_pressed = 0; +#ifdef GTK4_EXT + while (done_pressed == 0) { + g_main_context_iteration(NULL, TRUE); + } +#else XtAppContext app = _XtDefaultAppContext(); do { if (m == 0) { @@ -187,6 +210,7 @@ void phg_wsb_message( } m >>= 1; } while (done_pressed == 0); +#endif done_pressed = 0; } diff --git a/src/libphigs/ws/wsb.c b/src/libphigs/ws/wsb.c index e6e1edc..84a2be3 100644 --- a/src/libphigs/ws/wsb.c +++ b/src/libphigs/ws/wsb.c @@ -55,8 +55,10 @@ SOFTWARE. #include #include #include +#ifndef GTK4_EXT #include #include +#endif #include "phg.h" #include "private/phgP.h" @@ -854,7 +856,8 @@ void phg_wsb_traverse_all_postings( WSB_CHECK_POSTED(&owsb->posted); if( WSB_SOME_POSTED(&owsb->posted) ) { - /* Set up for complete traversal. */ + /* PASS 1: Opaque elements */ + wsgl_set_transparency_pass(ws, 0); post_str = owsb->posted.lowest.higher; end = &(owsb->posted.highest); wsgl_begin_rendering(ws); @@ -863,6 +866,20 @@ void phg_wsb_traverse_all_postings( post_str = post_str->higher; } wsgl_end_rendering(ws); + + /* PASS 2: Transparent elements (drawn with depth write off) */ + wsgl_set_transparency_pass(ws, 1); + post_str = owsb->posted.lowest.higher; + wsgl_begin_rendering(ws); + while ( post_str != end ) { + phg_wsb_traverse_net( ws, post_str->structh ); + post_str = post_str->higher; + } + wsgl_end_rendering(ws); + + /* Restore default state (Opaque) */ + wsgl_set_transparency_pass(ws, 0); + owsb->surf_state = PSURF_NOT_EMPTY; } } diff --git a/src/libphigs/ws/wsx.c b/src/libphigs/ws/wsx.c index e813490..6a049ba 100644 --- a/src/libphigs/ws/wsx.c +++ b/src/libphigs/ws/wsx.c @@ -23,8 +23,10 @@ #include #include #include +#ifndef GTK4_EXT #include #include +#endif #include #ifdef GLEW @@ -141,7 +143,11 @@ int phg_wsx_setup_tool( else { /* Initialize rendering context */ ws->app_context = phg_cpm_init_toolkit(argc, argv); +#ifdef GTK4_EXT + ws->top_level = (Widget)gtk_window_new(); +#else ws->top_level = XtInitialize("Workstation", "", NULL, 0, &argc, argv); +#endif /* Create window */ drawable_id = XCreateWindow(display, RootWindow(display, best_info->screen), diff --git a/src/libphigs/ws/wsx_inp.c b/src/libphigs/ws/wsx_inp.c index 602f3b0..74b6b61 100644 --- a/src/libphigs/ws/wsx_inp.c +++ b/src/libphigs/ws/wsx_inp.c @@ -28,8 +28,10 @@ #include "private/evtP.h" #include "private/wsxP.h" +#ifndef GTK4_EXT #include #include +#endif /******************************************************************************* * phg_wsx_input_dispatch_next @@ -43,8 +45,14 @@ int phg_wsx_input_dispatch_next( Phg_sin_evt_tbl *evt_tbl ) { - int status; + int status = FALSE; XEvent event; + +#ifdef GTK4_EXT + if (g_main_context_iteration(NULL, FALSE)) { + status = TRUE; + } +#else XtInputMask m; XtInputMask t; @@ -56,15 +64,13 @@ int phg_wsx_input_dispatch_next( status = TRUE; XtAppProcessEvent(ws->app_context, t & m); } +#endif if (XCheckWindowEvent(ws->display, ws->input_overlay_window, (unsigned long) 0xffffffffUL, &event) == True) { status = TRUE; } - else { - status = FALSE; - } return status; } diff --git a/src/libphigs/wsgl/wsgl.c b/src/libphigs/wsgl/wsgl.c index 26dd1fd..95bd8ab 100644 --- a/src/libphigs/wsgl/wsgl.c +++ b/src/libphigs/wsgl/wsgl.c @@ -49,6 +49,19 @@ short int wsgl_use_shaders = 1; short int wsgl_vert_shader_version = 120; short int wsgl_frag_shader_version = 120; +int wsgl_current_transparency_pass = 0; + +/******************************************************************************* + * wsgl_set_transparency_pass + * + * DESCR: Set the transparency pass and update HLHSR depth mask. + * RETURNS: N/A + ******************************************************************************/ +void wsgl_set_transparency_pass(Ws *ws, int pass) { + wsgl_current_transparency_pass = pass; + wsgl_update_hlhsr_id(ws); +} + #define LOG_INT(DATA) \ css_print_eltype(ELMT_HEAD(DATA)->elementType); \ printf(":\tSIZE: %d\t", ELMT_HEAD(DATA)->length); \ diff --git a/src/libphigs/wsgl/wsgl_attr.c b/src/libphigs/wsgl/wsgl_attr.c index a7c98b8..7bb21d5 100644 --- a/src/libphigs/wsgl/wsgl_attr.c +++ b/src/libphigs/wsgl/wsgl_attr.c @@ -364,7 +364,11 @@ void wsgl_update_hlhsr_id( case PHIGS_HLHSR_ID_ON: glDepthFunc(GL_LESS); - glDepthMask(GL_TRUE); + if (wsgl_current_transparency_pass == 1) { + glDepthMask(GL_FALSE); + } else { + glDepthMask(GL_TRUE); + } glEnable(GL_DEPTH_TEST); break; diff --git a/src/libphigs/wsgl/wsgl_line.c b/src/libphigs/wsgl/wsgl_line.c index 5decfb8..d50746c 100644 --- a/src/libphigs/wsgl/wsgl_line.c +++ b/src/libphigs/wsgl/wsgl_line.c @@ -51,6 +51,12 @@ void wsgl_polyline( point_list.points = (Ppoint *) &data[1]; wsgl_setup_line_attr(ast); + { + GLfloat cur_color[4]; + glGetFloatv(GL_CURRENT_COLOR, cur_color); + if (wsgl_current_transparency_pass == 0 && cur_color[3] < 1.0f) return; + if (wsgl_current_transparency_pass == 1 && cur_color[3] >= 1.0f) return; + } glBegin(GL_LINES); for (i = 0; i < point_list.num_points; i++) { glVertex2f(point_list.points[i].x, @@ -91,6 +97,12 @@ void wsgl_polyline3( point_list.points = (Ppoint3 *) &data[1]; wsgl_setup_line_attr(ast); + { + GLfloat cur_color[4]; + glGetFloatv(GL_CURRENT_COLOR, cur_color); + if (wsgl_current_transparency_pass == 0 && cur_color[3] < 1.0f) return; + if (wsgl_current_transparency_pass == 1 && cur_color[3] >= 1.0f) return; + } glBegin(GL_LINES); for (i = 0; i < point_list.num_points; i++) { glVertex3f(point_list.points[i].x, diff --git a/src/libphigs/wsgl/wsgl_marker.c b/src/libphigs/wsgl/wsgl_marker.c index 59a4e9d..4dc7ef5 100644 --- a/src/libphigs/wsgl/wsgl_marker.c +++ b/src/libphigs/wsgl/wsgl_marker.c @@ -225,6 +225,12 @@ void wsgl_polymarker( point_list.points = (Ppoint *) &data[1]; wsgl_setup_marker_attr(ast, &type, &size); + { + GLfloat cur_color[4]; + glGetFloatv(GL_CURRENT_COLOR, cur_color); + if (wsgl_current_transparency_pass == 0 && cur_color[3] < 1.0f) return; + if (wsgl_current_transparency_pass == 1 && cur_color[3] >= 1.0f) return; + } switch (type) { case PMARKER_DOT: wsgl_marker_polygon(40, &point_list, size); @@ -300,6 +306,12 @@ void wsgl_polymarker3( } wsgl_setup_marker_attr(ast, &type, &size); + { + GLfloat cur_color[4]; + glGetFloatv(GL_CURRENT_COLOR, cur_color); + if (wsgl_current_transparency_pass == 0 && cur_color[3] < 1.0f) return; + if (wsgl_current_transparency_pass == 1 && cur_color[3] >= 1.0f) return; + } switch (type) { case PMARKER_DOT: wsgl_marker_polygon(40, &plist, size); diff --git a/src/libphigs/wsgl/wsgl_shaders.c b/src/libphigs/wsgl/wsgl_shaders.c index ca245b6..208344d 100644 --- a/src/libphigs/wsgl/wsgl_shaders.c +++ b/src/libphigs/wsgl/wsgl_shaders.c @@ -20,8 +20,10 @@ #include #include #include +#ifndef GTK4_EXT #include #include +#endif #include #ifdef GLEW #include diff --git a/src/libphigs/wsgl/wsgl_tess.c b/src/libphigs/wsgl/wsgl_tess.c index 2c2fbf5..cbb022f 100644 --- a/src/libphigs/wsgl/wsgl_tess.c +++ b/src/libphigs/wsgl/wsgl_tess.c @@ -87,23 +87,9 @@ void wsgl_draw_tess_polygon(Wsgl_tess_vertex *vertices, int num_vertices, int re int normal_indices[MAX_VERTICES]; int n_vertices = 0; int n_normals = 0; - GLboolean orig_depth_mask; GLfloat cur_color[4]; int has_transparency = 0; - tess = gluNewTess(); - if (!tess) return; - - gluTessCallback(tess, GLU_TESS_BEGIN, (void (CALLBACK *)())tessBeginCB); - gluTessCallback(tess, GLU_TESS_END, (void (CALLBACK *)())tessEndCB); - gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK *)())tessVertexCB); - gluTessCallback(tess, GLU_TESS_ERROR, (void (CALLBACK *)())tessErrorCB); - gluTessCallback(tess, GLU_TESS_COMBINE, (void (CALLBACK *)())tessCombineCB); - gluTessCallback(tess, GLU_TESS_EDGE_FLAG, (void (CALLBACK *)())tessEdgeFlagCB); - - /* Determine if depth writing should be disabled for order-independent transparency */ - glGetBooleanv(GL_DEPTH_WRITEMASK, &orig_depth_mask); - if (num_vertices > 0 && vertices[0].apply_cb) { if (vertices[0].colr_type == PMODEL_RGBA && vertices[0].colr.direct.rgba.alpha < 1.0f) { has_transparency = 1; @@ -114,10 +100,19 @@ void wsgl_draw_tess_polygon(Wsgl_tess_vertex *vertices, int num_vertices, int re has_transparency = 1; } } - - if (has_transparency && orig_depth_mask == GL_TRUE) { - glDepthMask(GL_FALSE); - } + + if (wsgl_current_transparency_pass == 0 && has_transparency) return; + if (wsgl_current_transparency_pass == 1 && !has_transparency) return; + + tess = gluNewTess(); + if (!tess) return; + + gluTessCallback(tess, GLU_TESS_BEGIN, (void (CALLBACK *)())tessBeginCB); + gluTessCallback(tess, GLU_TESS_END, (void (CALLBACK *)())tessEndCB); + gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK *)())tessVertexCB); + gluTessCallback(tess, GLU_TESS_ERROR, (void (CALLBACK *)())tessErrorCB); + gluTessCallback(tess, GLU_TESS_COMBINE, (void (CALLBACK *)())tessCombineCB); + gluTessCallback(tess, GLU_TESS_EDGE_FLAG, (void (CALLBACK *)())tessEdgeFlagCB); gluTessBeginPolygon(tess, NULL); gluTessBeginContour(tess); @@ -144,10 +139,6 @@ void wsgl_draw_tess_polygon(Wsgl_tess_vertex *vertices, int num_vertices, int re /* Restore default edge flag state for subsequent rendering */ glEdgeFlag(GL_TRUE); - if (has_transparency && orig_depth_mask == GL_TRUE) { - glDepthMask(GL_TRUE); - } - if (record_geom_flag && n_vertices > 0) { wsgl_add_geometry(GEOM_FACE, vertex_indices, normal_indices, n_vertices); } diff --git a/src/libphigs/wsgl/wsgl_text.c b/src/libphigs/wsgl/wsgl_text.c index 79ff1e8..2a97c30 100644 --- a/src/libphigs/wsgl/wsgl_text.c +++ b/src/libphigs/wsgl/wsgl_text.c @@ -425,6 +425,12 @@ static void wsgl_text_string( int n_vertices = 0; wsgl_setup_text_attr(ast, &fnt, &char_expan); + { + GLfloat cur_color[4]; + glGetFloatv(GL_CURRENT_COLOR, cur_color); + if (wsgl_current_transparency_pass == 0 && cur_color[3] < 1.0f) return; + if (wsgl_current_transparency_pass == 1 && cur_color[3] >= 1.0f) return; + } char_ht = ast->char_ht; posa.x = text->pos.x; @@ -496,6 +502,12 @@ static void wsgl_text_string3( int n_vertices = 0; wsgl_setup_text_attr(ast, &fnt, &char_expan); + { + GLfloat cur_color[4]; + glGetFloatv(GL_CURRENT_COLOR, cur_color); + if (wsgl_current_transparency_pass == 0 && cur_color[3] < 1.0f) return; + if (wsgl_current_transparency_pass == 1 && cur_color[3] >= 1.0f) return; + } char_ht = ast->char_ht; posa.x = text->pos.x; @@ -568,6 +580,12 @@ static void wsgl_anno_text_string3( int n_vertices = 0; wsgl_setup_text_attr(ast, &fnt, &char_expan); + { + GLfloat cur_color[4]; + glGetFloatv(GL_CURRENT_COLOR, cur_color); + if (wsgl_current_transparency_pass == 0 && cur_color[3] < 1.0f) return; + if (wsgl_current_transparency_pass == 1 && cur_color[3] >= 1.0f) return; + } char_ht = ast->anno_char_ht; posa.x = text->pos.x;