Fix terminal search field not unfocusing when REI focused

This commit is contained in:
Shadowfacts 2021-12-23 11:36:46 -05:00
parent c5ede3bd62
commit ef9aa9e958
11 changed files with 95 additions and 56 deletions

View File

@ -1,5 +1,7 @@
package net.shadowfacts.phycon.plugin.rei package net.shadowfacts.phycon.plugin.rei
import dev.architectury.event.EventResult
import dev.architectury.event.events.client.ClientScreenInputEvent
import me.shedaniel.math.Rectangle import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.REIRuntime import me.shedaniel.rei.api.client.REIRuntime
import me.shedaniel.rei.api.client.plugins.REIClientPlugin import me.shedaniel.rei.api.client.plugins.REIClientPlugin
@ -15,15 +17,17 @@ object PhyConPluginClient: ClientModInitializer, REIClientPlugin {
const val MODID = "phycon_rei" const val MODID = "phycon_rei"
override fun onInitializeClient() { override fun onInitializeClient() {
AbstractTerminalScreen.registerClickHandler { mouseX, mouseY, button -> ClientScreenInputEvent.MOUSE_RELEASED_PRE.register { client, screen, mouseX, mouseY, button ->
if (screen is AbstractTerminalScreen<*, *>) {
REIRuntime.getInstance().searchTextField?.also { REIRuntime.getInstance().searchTextField?.also {
if (it.isFocused) { if (it.isFocused) {
this.terminalVC.searchField.resignFirstResponder() screen.terminalVC.searchField.resignFirstResponder()
} else { } else {
this.terminalVC.searchField.becomeFirstResponder() screen.terminalVC.searchField.becomeFirstResponder()
} }
} }
null }
EventResult.pass()
} }
} }

View File

@ -0,0 +1,28 @@
package net.shadowfacts.phycon.mixin.client;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.shadowfacts.cacao.AbstractCacaoScreen;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* @author shadowfacts
*/
@Mixin(MinecraftClient.class)
public class MixinMinecraftClient {
@Inject(
method = "setScreen(Lnet/minecraft/client/gui/screen/Screen;)V",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", opcode = Opcodes.PUTFIELD, shift = At.Shift.AFTER)
)
private void setScreen(Screen screen, CallbackInfo ci) {
if (screen instanceof AbstractCacaoScreen) {
((AbstractCacaoScreen)screen).screenWillAppear();
}
}
}

View File

@ -14,4 +14,6 @@ interface AbstractCacaoScreen {
fun removeWindow(window: Window) fun removeWindow(window: Window)
fun screenWillAppear()
} }

View File

@ -1,5 +1,6 @@
package net.shadowfacts.cacao package net.shadowfacts.cacao
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
@ -29,10 +30,16 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
override val windows: List<Window> = _windows override val windows: List<Window> = _windows
private var hasAppeared = false
override fun <T: Window> addWindow(window: T, index: Int): T { override fun <T: Window> addWindow(window: T, index: Int): T {
if (window is ScreenHandlerWindow && window.screenHandler != handler) { if (window is ScreenHandlerWindow && window.screenHandler != handler) {
throw RuntimeException("Adding ScreenHandlerWindow to CacaoHandledScreen with different screen handler is not supported") throw RuntimeException("Adding ScreenHandlerWindow to CacaoHandledScreen with different screen handler is not supported")
} }
if (hasAppeared) {
window.viewController.viewWillAppear()
}
_windows.add(index, window) _windows.add(index, window)
@ -54,6 +61,12 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
} }
} }
override fun screenWillAppear() {
windows.forEach {
it.viewController.viewWillAppear()
}
}
override fun init() { override fun init() {
super.init() super.init()
@ -66,7 +79,8 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
super.onClose() super.onClose()
windows.forEach { windows.forEach {
// todo: VC callbacks it.viewController.viewWillDisappear()
it.viewController.viewDidDisappear()
it.firstResponder = null it.firstResponder = null
} }

View File

@ -1,5 +1,6 @@
package net.shadowfacts.cacao package net.shadowfacts.cacao
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.screen.Screen import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
import net.minecraft.sound.SoundEvents import net.minecraft.sound.SoundEvents
@ -32,6 +33,8 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
*/ */
override val windows: List<Window> = _windows override val windows: List<Window> = _windows
private var hasAppeared = false
/** /**
* Adds the given window to this screen's window list at the given position. * Adds the given window to this screen's window list at the given position.
* *
@ -40,6 +43,10 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
* @return The window that was added, as a convenience. * @return The window that was added, as a convenience.
*/ */
override fun <T: Window> addWindow(window: T, index: Int): T { override fun <T: Window> addWindow(window: T, index: Int): T {
if (hasAppeared) {
window.viewController.viewWillAppear()
}
_windows.add(index, window) _windows.add(index, window)
window.screen = this window.screen = this
@ -66,8 +73,14 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
} }
} }
override fun init() { override fun screenWillAppear() {
super.init() windows.forEach {
it.viewController.viewWillAppear()
}
}
override fun resize(client: MinecraftClient, width: Int, height: Int) {
super.resize(client, width, height)
windows.forEach { windows.forEach {
it.resize(width, height) it.resize(width, height)
@ -78,7 +91,8 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
super.onClose() super.onClose()
windows.forEach { windows.forEach {
// todo: VC callbacks it.viewController.viewWillDisappear()
it.viewController.viewDidDisappear()
// resign the current first responder (if any) // resign the current first responder (if any)
it.firstResponder = null it.firstResponder = null

View File

@ -147,11 +147,6 @@ class TabViewController<T: TabViewController.Tab>(
currentTabController.viewWillAppear() currentTabController.viewWillAppear()
} }
override fun viewDidAppear() {
super.viewDidAppear()
currentTabController.viewDidAppear()
}
override fun viewWillDisappear() { override fun viewWillDisappear() {
super.viewWillDisappear() super.viewWillDisappear()
currentTabController.viewWillDisappear() currentTabController.viewWillDisappear()
@ -225,7 +220,6 @@ class TabViewController<T: TabViewController.Tab>(
embedChild(currentTabController, tabVCContainer) embedChild(currentTabController, tabVCContainer)
currentTabController.didMoveTo(this) currentTabController.didMoveTo(this)
currentTabController.viewWillAppear() currentTabController.viewWillAppear()
currentTabController.viewDidAppear()
onTabChange?.invoke(currentTab) onTabChange?.invoke(currentTab)

View File

@ -122,12 +122,12 @@ abstract class ViewController {
children.forEach(ViewController::viewWillAppear) children.forEach(ViewController::viewWillAppear)
} }
/** // /**
* Called immediately after the VC's view has first been displayed on screen. // * Called immediately after the VC's view has first been displayed on screen.
*/ // */
open fun viewDidAppear() { // open fun viewDidAppear() {
children.forEach(ViewController::viewDidAppear) // children.forEach(ViewController::viewDidAppear)
} // }
/** /**
* Called before the view will disappear from the screen, either because the VC has been removed from it's parent/screen * Called before the view will disappear from the screen, either because the VC has been removed from it's parent/screen

View File

@ -4,7 +4,6 @@ import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawableHelper import net.minecraft.client.gui.DrawableHelper
import net.minecraft.client.gui.Element import net.minecraft.client.gui.Element
import net.minecraft.client.gui.widget.TextFieldWidget
import net.minecraft.client.render.GameRenderer import net.minecraft.client.render.GameRenderer
import net.minecraft.client.render.Tessellator import net.minecraft.client.render.Tessellator
import net.minecraft.client.render.VertexConsumerProvider import net.minecraft.client.render.VertexConsumerProvider
@ -13,7 +12,6 @@ import net.minecraft.entity.player.PlayerInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.screen.slot.Slot import net.minecraft.screen.slot.Slot
import net.minecraft.screen.slot.SlotActionType import net.minecraft.screen.slot.SlotActionType
import net.minecraft.text.LiteralText
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.shadowfacts.cacao.CacaoHandledScreen import net.shadowfacts.cacao.CacaoHandledScreen
@ -23,7 +21,6 @@ import net.shadowfacts.phycon.networking.C2STerminalRequestItem
import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems
import java.math.RoundingMode import java.math.RoundingMode
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.LinkedList
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.min import kotlin.math.min
@ -38,14 +35,6 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
val terminalBackgroundHeight: Int, val terminalBackgroundHeight: Int,
): CacaoHandledScreen<T>(handler, playerInv, title) { ): CacaoHandledScreen<T>(handler, playerInv, title) {
companion object {
private val clickHandlers = LinkedList<AbstractTerminalScreen<*, *>.(Double, Double, Int) -> Boolean?>()
fun registerClickHandler(handler: AbstractTerminalScreen<*, *>.(Double, Double, Int) -> Boolean?) {
clickHandlers.add(handler)
}
}
abstract val backgroundTexture: Identifier abstract val backgroundTexture: Identifier
val terminalVC: AbstractTerminalViewController<*, *, *> val terminalVC: AbstractTerminalViewController<*, *, *>
@ -160,17 +149,6 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
} }
} }
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
for (handler in clickHandlers) {
val res = handler(mouseX, mouseY, button)
if (res != null) {
return res
}
}
return super.mouseClicked(mouseX, mouseY, button)
}
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) { override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) {
super.onMouseClick(slot, invSlot, clickData, type) super.onMouseClick(slot, invSlot, clickData, type)
@ -191,12 +169,11 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
} }
} }
private val fakeFocusedElement = TextFieldWidget(textRenderer, 0, 0, 0, 0, LiteralText("")) override fun setFocused(element: Element?) {
override fun getFocused(): Element? { super.setFocused(element)
return if (windows.last().firstResponder != null) { // so that when something else (e.g., REI) steals focus and calls setFocused(null) on us, any first responder resigns
fakeFocusedElement if (element == null) {
} else { windows.last().firstResponder?.resignFirstResponder()
null
} }
} }

View File

@ -100,7 +100,6 @@ abstract class AbstractTerminalViewController<BE: AbstractTerminalBlockEntity, S
handler = ::searchFieldChanged handler = ::searchFieldChanged
drawBackground = false drawBackground = false
} }
searchField.becomeFirstResponder()
scrollTrack = view.addSubview(ScrollTrackView(::scrollPositionChanged)) scrollTrack = view.addSubview(ScrollTrackView(::scrollPositionChanged))
@ -137,6 +136,12 @@ abstract class AbstractTerminalViewController<BE: AbstractTerminalBlockEntity, S
} }
} }
override fun viewWillAppear() {
super.viewWillAppear()
searchField.becomeFirstResponder()
}
private fun searchFieldChanged(field: TextField) { private fun searchFieldChanged(field: TextField) {
screen.searchQuery = field.text screen.searchQuery = field.text
screen.requestUpdatedItems() screen.requestUpdatedItems()

View File

@ -1,9 +1,10 @@
{ {
"required": true, "required": true,
"package": "net.shadowfacts.phycon.mixin.client", "package": "net.shadowfacts.phycon.mixin.client",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_17",
"mixins": [ "mixins": [
"MixinHandledScreen", "MixinHandledScreen",
"MixinMinecraftClient",
"TextFieldWidgetAccessor" "TextFieldWidgetAccessor"
], ],
"injectors": { "injectors": {

View File

@ -1,7 +1,7 @@
{ {
"required": true, "required": true,
"package": "net.shadowfacts.phycon.mixin", "package": "net.shadowfacts.phycon.mixin",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_17",
"mixins": [ "mixins": [
], ],
"injectors": { "injectors": {