“From what I have seen, Oracle applies the WHERE predicate before determining what rows to skip.”
Yup. It is the only possible way. You can’t skip a row from a resultset until you have determined the resultset.
The answer is simply not to limit the number of rows returned by the SELECT statement. You can still use the FIRST_ROWS_n hints to direct the optimizer that you won’t be grabbing the full data set.
The software calling the SELECT should only select the first n rows. In PL/SQL, it would be
DECLARE
CURSOR c_1 IS
SELECT /*+FIRST_ROWS_1*/ qt.ID
FROM QueueTest qt
WHERE Locked IS NULL
ORDER BY PRIORITY
FOR UPDATE SKIP LOCKED;
BEGIN
OPEN c_1;
FETCH c_1 into ....
IF c_1%FOUND THEN
...
END IF;
CLOSE c_1;
END;