916 "wait-for and process events. |
916 "wait-for and process events. |
917 Stay in this loop while there are still any views to dispatch for, |
917 Stay in this loop while there are still any views to dispatch for, |
918 and aBlock evaluates to true. |
918 and aBlock evaluates to true. |
919 |
919 |
920 Some signals are caught & handled: |
920 Some signals are caught & handled: |
921 LeaveSignal forces an exit from the eventLoop; |
921 LeaveSignal forces an exit from the eventLoop; |
922 AbortSignal brings us back into the loop, processing the next event; |
922 AbortSignal brings us back into the loop, processing the next event; |
923 ActivityNotifications send a #showActivity: if nonModal, |
923 ActivityNotifications send a #showActivity: if nonModal, |
924 otherwise they are ignored." |
924 otherwise they are ignored." |
925 |
925 |
926 |thisProcess sigs mainSema prevSema| |
926 |thisProcess sigs mainSema prevSema| |
927 |
927 |
928 thisProcess := Processor activeProcess. |
928 thisProcess := Processor activeProcess. |
929 |
929 |
930 sigs := SignalSet |
930 sigs := SignalSet |
931 with:AbortSignal |
931 with:AbortSignal |
932 with:LeaveSignal |
932 with:LeaveSignal |
933 with:(self class activityNotificationSignal). |
933 with:(self class activityNotificationSignal). |
934 |
934 |
935 [ |
935 [ |
936 |p g s mainGroup mySema waitSema groupForSema| |
936 |p g s mainGroup mySema waitSema groupForSema| |
937 |
937 |
938 waitSema := mySema := mySensor eventSemaphore. |
938 waitSema := mySema := mySensor eventSemaphore. |
939 |
939 |
940 isModal ifTrue:[ |
940 isModal ifTrue:[ |
941 mainGroup := self mainGroup. |
941 mainGroup := self mainGroup. |
942 mainGroup == self ifTrue:[ |
942 mainGroup == self ifTrue:[ |
943 mainGroup := nil |
943 mainGroup := nil |
944 ]. |
944 ]. |
945 ] ifFalse:[ |
945 ] ifFalse:[ |
946 mainGroup := previousGroup |
946 mainGroup := previousGroup |
947 ]. |
947 ]. |
948 |
948 |
949 mainGroup notNil ifTrue:[ |
949 mainGroup notNil ifTrue:[ |
950 mainSema := mainGroup sensor eventSemaphore. |
950 mainSema := mainGroup sensor eventSemaphore. |
951 waitSema := SemaphoreSet with:mySema with:mainSema. |
951 waitSema := SemaphoreSet with:mySema with:mainSema. |
952 |
952 |
953 "/ must also care for all other groups in between |
953 "/ must also care for all other groups in between |
954 "/ (in case its a modal dialog opened from a modal dialog) |
954 "/ (in case its a modal dialog opened from a modal dialog) |
955 |
955 |
956 g := previousGroup. |
956 g := previousGroup. |
957 g ~~ mainGroup ifTrue:[ |
957 g ~~ mainGroup ifTrue:[ |
958 groupForSema := IdentityDictionary new. |
958 groupForSema := IdentityDictionary new. |
959 [g ~~ mainGroup] whileTrue:[ |
959 [g ~~ mainGroup] whileTrue:[ |
960 s := g sensor eventSemaphore. |
960 s := g sensor eventSemaphore. |
961 waitSema add:s. |
961 waitSema add:s. |
962 groupForSema at:s put:g. |
962 groupForSema at:s put:g. |
963 g := g previousGroup. |
963 g := g previousGroup. |
964 ] |
964 ] |
965 ]. |
965 ]. |
966 ]. |
966 ]. |
967 |
967 |
968 [aBlock value] whileTrue:[ |
968 [aBlock value] whileTrue:[ |
969 LastActiveGroup := self. |
969 LastActiveGroup := self. |
970 LastActiveProcess := thisProcess. |
970 LastActiveProcess := thisProcess. |
971 |
971 |
972 (views isNil and:[topViews isNil]) ifTrue:[ |
972 (views isNil and:[topViews isNil]) ifTrue:[ |
973 myProcess notNil ifTrue:[ |
973 myProcess notNil ifTrue:[ |
974 p := myProcess. |
974 p := myProcess. |
975 myProcess := nil. |
975 myProcess := nil. |
976 p terminate. |
976 p terminate. |
977 "not reached - there is no life after death" |
977 "not reached - there is no life after death" |
978 ]. |
978 ]. |
979 " |
979 " |
980 this is the end of a modal loop |
980 this is the end of a modal loop |
981 (not having a private process ...) |
981 (not having a private process ...) |
982 " |
982 " |
983 ^ self |
983 ^ self |
984 ]. |
984 ]. |
985 |
985 |
986 sigs handle:[:ex | |
986 sigs handle:[:ex | |
987 |theSig| |
987 |theSig| |
988 |
988 |
989 (theSig := ex signal) == AbortSignal ifTrue:[ |
989 (theSig := ex signal) == AbortSignal ifTrue:[ |
990 "/ |
990 "/ |
991 "/ on abort, stay in loop |
991 "/ on abort, stay in loop |
992 "/ |
992 "/ |
993 ex return |
993 ex return |
994 ]. |
994 ]. |
995 theSig == LeaveSignal ifTrue:[ |
995 theSig == LeaveSignal ifTrue:[ |
996 "/ |
996 "/ |
997 "/ on leave, exit the event loop |
997 "/ on leave, exit the event loop |
998 "/ |
998 "/ |
999 ^ self |
999 ^ self |
1000 ]. |
1000 ]. |
1001 |
1001 |
1002 "/ ActivityNotification |
1002 "/ ActivityNotification |
1003 "/ |
1003 "/ |
1004 "/ if I am a modal-group, let it be handled |
1004 "/ if I am a modal-group, let it be handled |
1005 "/ by the outer main-groups handler |
1005 "/ by the outer main-groups handler |
1006 "/ otherwise show the activityMessage and continue. |
1006 "/ otherwise show the activityMessage and continue. |
1007 "/ |
1007 "/ |
1008 isModal ifTrue:[ |
1008 isModal ifTrue:[ |
1009 ex reject |
1009 ex reject |
1010 "never reached" |
1010 "never reached" |
1011 ]. |
1011 ]. |
1012 self showActivity:(ex errorString). |
1012 self showActivity:(ex errorString). |
1013 ex proceed. |
1013 ex proceed. |
1014 ] do:[ |
1014 ] do:[ |
1015 |dev gotSema mainView| |
1015 |dev gotSema mainView| |
1016 |
1016 |
1017 "/ Flush device output before going to sleep. |
1017 "/ Flush device output before going to sleep. |
1018 "/ This may produce more events to arrive. |
1018 "/ This may produce more events to arrive. |
1019 "/ Q: is this still needed (see suspendAction) ? |
1019 "/ Q: is this still needed (see suspendAction) ? |
1020 |
1020 |
1021 "/ dev := self graphicsDevice. |
1021 "/ dev := self graphicsDevice. |
1022 "/ dev notNil ifTrue:[dev flush]. |
1022 "/ dev notNil ifTrue:[dev flush]. |
1023 |
1023 |
1024 "/ now, wait for an event to arrive |
1024 (mainGroup notNil or:[mySensor hasEvents not]) ifTrue:[ |
1025 thisProcess setStateTo:#eventWait if:#active. |
1025 "/ now, wait for an event to arrive |
1026 waitSema isNil ifTrue:[ |
1026 thisProcess setStateTo:#eventWait if:#active. |
1027 "/ oops - how can this happen .... |
1027 waitSema isNil ifTrue:[ |
1028 ^ self. |
1028 "/ oops - how can this happen .... |
1029 ]. |
1029 ^ self. |
1030 gotSema := waitSema wait. |
1030 ]. |
1031 LastActiveGroup := self. |
1031 gotSema := waitSema wait. |
1032 LastActiveProcess := thisProcess. |
1032 ] ifFalse:[ |
1033 |
1033 gotSema := mySema |
1034 "/ some bad guy ;-) could have closed all down |
1034 ]. |
1035 "/ in the meanwhile ... |
1035 LastActiveGroup := self. |
1036 |
1036 LastActiveProcess := thisProcess. |
1037 mySensor notNil ifTrue:[ |
1037 |
1038 gotSema == mySema ifTrue:[ |
1038 "/ some bad guy ;-) could have closed all down |
1039 "/ |
1039 "/ in the meanwhile ... |
1040 "/ an event for me |
1040 |
1041 "/ |
1041 mySensor notNil ifTrue:[ |
1042 self processEventsWithModalGroup:nil |
1042 gotSema == mySema ifTrue:[ |
1043 ] ifFalse:[ |
1043 "/ |
1044 groupForSema notNil ifTrue:[ |
1044 "/ an event for me |
1045 g := groupForSema at:gotSema ifAbsent:nil. |
1045 "/ |
1046 g := g ? mainGroup. |
1046 self processEventsWithModalGroup:nil |
1047 ] ifFalse:[ |
1047 ] ifFalse:[ |
1048 g := mainGroup |
1048 groupForSema notNil ifTrue:[ |
1049 ]. |
1049 g := groupForSema at:gotSema ifAbsent:nil. |
1050 |
1050 g := g ? mainGroup. |
1051 "/ |
1051 ] ifFalse:[ |
1052 "/ an event for my mainGroup |
1052 g := mainGroup |
1053 "/ |
1053 ]. |
1054 g topViews notNil ifTrue:[ |
1054 |
1055 mainView := g topViews first |
1055 "/ |
1056 ]. |
1056 "/ an event for my mainGroup |
1057 mainView notNil ifTrue:[ |
1057 "/ |
1058 "/ |
1058 g topViews notNil ifTrue:[ |
1059 "/ if anything happened to the mainGroup |
1059 mainView := g topViews first |
1060 "/ bring my own topView back to the front |
1060 ]. |
1061 "/ This keeps modalBoxes visible |
1061 mainView notNil ifTrue:[ |
1062 "/ |
1062 "/ |
1063 (g sensor hasConfigureEventFor:mainView) ifTrue:[ |
1063 "/ if anything happened to the mainGroup |
1064 topViews size > 0 ifTrue:[ |
1064 "/ bring my own topView back to the front |
1065 topViews first raiseDeiconified |
1065 "/ This keeps modalBoxes visible |
1066 ] |
1066 "/ |
1067 ] |
1067 (g sensor hasConfigureEventFor:mainView) ifTrue:[ |
1068 ]. |
1068 topViews size > 0 ifTrue:[ |
1069 " |
1069 topViews first raiseDeiconified |
1070 if modal, also check for redraw events in my maingroup |
1070 ] |
1071 (we arrive here after we woke up on maingroup sensor eventSemaphore) |
1071 ] |
1072 " |
1072 ]. |
1073 g processEventsWithModalGroup:self. |
1073 " |
1074 ] |
1074 if modal, also check for redraw events in my maingroup |
1075 ] |
1075 (we arrive here after we woke up on maingroup sensor eventSemaphore) |
1076 ]. |
1076 " |
1077 ]. |
1077 g processEventsWithModalGroup:self. |
|
1078 ] |
|
1079 ] |
|
1080 ]. |
|
1081 ]. |
1078 ] valueNowOrOnUnwindDo:[ |
1082 ] valueNowOrOnUnwindDo:[ |
1079 "/ |
1083 "/ |
1080 "/ perform any cleanupActions |
1084 "/ perform any cleanupActions |
1081 "/ |
1085 "/ |
1082 cleanupActions notNil ifTrue:[cleanupActions value] |
1086 cleanupActions notNil ifTrue:[cleanupActions value] |
1083 ] |
1087 ] |
1084 |
1088 |
1085 "Modified: / 14.12.1995 / 11:12:24 / stefan" |
1089 "Modified: / 14.12.1995 / 11:12:24 / stefan" |
1086 "Modified: / 4.8.1998 / 18:17:59 / cg" |
1090 "Modified: / 5.2.1999 / 22:32:07 / cg" |
1087 ! |
1091 ! |
1088 |
1092 |
1089 leaveEventLoop |
1093 leaveEventLoop |
1090 "immediately leave the event loop, returning way back. |
1094 "immediately leave the event loop, returning way back. |
1091 This can be used to leave (and closedown) a modal group. |
1095 This can be used to leave (and closedown) a modal group. |